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

lightningnetwork / lnd / 15858991938

24 Jun 2025 06:51PM UTC coverage: 55.808% (-2.4%) from 58.173%
15858991938

Pull #9148

github

web-flow
Merge 0e921d6a5 into 29ff13d83
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

232 of 267 new or added lines in 5 files covered. (86.89%)

24606 existing lines in 281 files now uncovered.

108380 of 194201 relevant lines covered (55.81%)

22488.12 hits per line

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

0.0
/autopilot/combinedattach.go
1
package autopilot
2

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

7
        "github.com/btcsuite/btcd/btcutil"
8
)
9

10
// WeightedHeuristic is a tuple that associates a weight to an
11
// AttachmentHeuristic. This is used to determining a node's final score when
12
// querying several heuristics for scores.
13
type WeightedHeuristic struct {
14
        // Weight is this AttachmentHeuristic's relative weight factor. It
15
        // should be between 0.0 and 1.0.
16
        Weight float64
17

18
        AttachmentHeuristic
19
}
20

21
// WeightedCombAttachment is an implementation of the AttachmentHeuristic
22
// interface that combines the scores given by several sub-heuristics into one.
23
type WeightedCombAttachment struct {
24
        heuristics []*WeightedHeuristic
25
}
26

27
// NewWeightedCombAttachment creates a new instance of a WeightedCombAttachment.
28
func NewWeightedCombAttachment(h ...*WeightedHeuristic) (
UNCOV
29
        *WeightedCombAttachment, error) {
×
UNCOV
30

×
UNCOV
31
        // The sum of weights given to the sub-heuristics must sum to exactly
×
UNCOV
32
        // 1.0.
×
UNCOV
33
        var sum float64
×
UNCOV
34
        for _, w := range h {
×
UNCOV
35
                sum += w.Weight
×
UNCOV
36
        }
×
37

UNCOV
38
        if sum != 1.0 {
×
39
                return nil, fmt.Errorf("weights MUST sum to 1.0 (was %v)", sum)
×
40
        }
×
41

UNCOV
42
        return &WeightedCombAttachment{
×
UNCOV
43
                heuristics: h,
×
UNCOV
44
        }, nil
×
45
}
46

47
// A compile time assertion to ensure WeightedCombAttachment meets the
48
// AttachmentHeuristic and ScoreSettable interfaces.
49
var _ AttachmentHeuristic = (*WeightedCombAttachment)(nil)
50
var _ ScoreSettable = (*WeightedCombAttachment)(nil)
51

52
// Name returns the name of this heuristic.
53
//
54
// NOTE: This is a part of the AttachmentHeuristic interface.
55
func (c *WeightedCombAttachment) Name() string {
×
56
        return "weightedcomb"
×
57
}
×
58

59
// NodeScores is a method that given the current channel graph, current set of
60
// local channels and funds available, scores the given nodes according to the
61
// preference of opening a channel with them. The returned channel candidates
62
// maps the NodeID to an attachment directive containing a score and a channel
63
// size.
64
//
65
// The scores is determined by querying the set of sub-heuristics, then
66
// combining these scores into a final score according to the active
67
// configuration.
68
//
69
// The returned scores will be in the range [0, 1.0], where 0 indicates no
70
// improvement in connectivity if a channel is opened to this node, while 1.0
71
// is the maximum possible improvement in connectivity.
72
//
73
// NOTE: This is a part of the AttachmentHeuristic interface.
74
func (c *WeightedCombAttachment) NodeScores(ctx context.Context, g ChannelGraph,
75
        chans []LocalChannel, chanSize btcutil.Amount,
76
        nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
×
77

×
78
        // We now query each heuristic to determine the score they give to the
×
79
        // nodes for the given channel size.
×
80
        var subScores []map[NodeID]*NodeScore
×
81
        for _, h := range c.heuristics {
×
82
                log.Tracef("Getting scores from sub heuristic %v", h.Name())
×
83

×
84
                s, err := h.NodeScores(
×
85
                        ctx, g, chans, chanSize, nodes,
×
86
                )
×
87
                if err != nil {
×
88
                        return nil, fmt.Errorf("unable to get sub score: %w",
×
89
                                err)
×
90
                }
×
91

92
                subScores = append(subScores, s)
×
93
        }
94

95
        // We combine the scores given by the sub-heuristics by using the
96
        // heuristics' given weight factor.
97
        scores := make(map[NodeID]*NodeScore)
×
98
        for nID := range nodes {
×
99
                score := &NodeScore{
×
100
                        NodeID: nID,
×
101
                }
×
102

×
103
                // Each sub-heuristic should have scored the node, if not it is
×
104
                // implicitly given a zero score by that heuristic.
×
105
                for i, h := range c.heuristics {
×
106
                        sub, ok := subScores[i][nID]
×
107
                        if !ok {
×
108
                                log.Tracef("No score given to node %x by sub "+
×
109
                                        "heuristic %v", nID[:], h.Name())
×
110
                                continue
×
111
                        }
112
                        // Use the heuristic's weight factor to determine of
113
                        // how much weight we should give to this particular
114
                        // score.
115
                        subScore := h.Weight * sub.Score
×
116
                        log.Tracef("Giving node %x a sub score of %v "+
×
117
                                "(%v * %v) from sub heuristic %v", nID[:],
×
118
                                subScore, h.Weight, sub.Score, h.Name())
×
119

×
120
                        score.Score += subScore
×
121
                }
122

123
                log.Tracef("Node %x got final combined score %v", nID[:],
×
124
                        score.Score)
×
125

×
126
                switch {
×
127
                // Instead of adding a node with score 0 to the returned set,
128
                // we just skip it.
129
                case score.Score == 0:
×
130
                        continue
×
131

132
                // Sanity check the new score.
133
                case score.Score < 0 || score.Score > 1.0:
×
134
                        return nil, fmt.Errorf("invalid node score from "+
×
135
                                "combination: %v", score.Score)
×
136
                }
137

138
                scores[nID] = score
×
139
        }
140

141
        return scores, nil
×
142
}
143

144
// SetNodeScores is used to set the internal map from NodeIDs to scores. The
145
// passed scores must be in the range [0, 1.0]. The fist parameter is the name
146
// of the targeted heuristic, to allow recursively target specific
147
// sub-heuristics. The returned boolean indicates whether the targeted
148
// heuristic was found.
149
//
150
// Since this heuristic doesn't keep any internal scores, it will recursively
151
// apply the scores to its sub-heuristics.
152
//
153
// NOTE: This is a part of the ScoreSettable interface.
154
func (c *WeightedCombAttachment) SetNodeScores(targetHeuristic string,
155
        newScores map[NodeID]float64) (bool, error) {
×
156

×
157
        found := false
×
158
        for _, h := range c.heuristics {
×
159
                // It must be ScoreSettable to be available for external
×
160
                // scores.
×
161
                s, ok := h.AttachmentHeuristic.(ScoreSettable)
×
162
                if !ok {
×
163
                        continue
×
164
                }
165

166
                // Heuristic supports scoring, attempt to set them.
167
                applied, err := s.SetNodeScores(targetHeuristic, newScores)
×
168
                if err != nil {
×
169
                        return false, err
×
170
                }
×
171
                found = found || applied
×
172
        }
173

174
        return found, nil
×
175
}
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