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

lightningnetwork / lnd / 13536249039

26 Feb 2025 03:42AM UTC coverage: 57.462% (-1.4%) from 58.835%
13536249039

Pull #8453

github

Roasbeef
peer: update chooseDeliveryScript to gen script if needed

In this commit, we update `chooseDeliveryScript` to generate a new
script if needed. This allows us to fold in a few other lines that
always followed this function into this expanded function.

The tests have been updated accordingly.
Pull Request #8453: [4/4] - multi: integrate new rbf coop close FSM into the existing peer flow

275 of 1318 new or added lines in 22 files covered. (20.86%)

19521 existing lines in 257 files now uncovered.

103858 of 180741 relevant lines covered (57.46%)

24750.23 hits per line

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

96.0
/watchtower/wtclient/candidate_iterator.go
1
package wtclient
2

3
import (
4
        "container/list"
5
        "net"
6
        "sync"
7

8
        "github.com/lightningnetwork/lnd/watchtower/wtdb"
9
)
10

11
// TowerCandidateIterator provides an abstraction for iterating through possible
12
// watchtower addresses when attempting to create a new session.
13
type TowerCandidateIterator interface {
14
        // AddCandidate adds a new candidate tower to the iterator. If the
15
        // candidate already exists, then any new addresses are added to it.
16
        AddCandidate(*Tower)
17

18
        // RemoveCandidate removes an existing candidate tower from the
19
        // iterator. An optional address can be provided to indicate a stale
20
        // tower address to remove it. If it isn't provided, then the tower is
21
        // completely removed from the iterator.
22
        RemoveCandidate(wtdb.TowerID, net.Addr) error
23

24
        // IsActive determines whether a given tower is exists within the
25
        // iterator.
26
        IsActive(wtdb.TowerID) bool
27

28
        // Reset clears any internal iterator state, making previously taken
29
        // candidates available as long as they remain in the set.
30
        Reset() error
31

32
        // GetTower gets the tower with the given ID from the iterator. If no
33
        // such tower is found then ErrTowerNotInIterator is returned.
34
        GetTower(id wtdb.TowerID) (*Tower, error)
35

36
        // Next returns the next candidate tower. The iterator is not required
37
        // to return results in any particular order.  If no more candidates are
38
        // available, ErrTowerCandidatesExhausted is returned.
39
        Next() (*Tower, error)
40
}
41

42
// towerListIterator is a linked-list backed TowerCandidateIterator.
43
type towerListIterator struct {
44
        mu            sync.Mutex
45
        queue         *list.List
46
        nextCandidate *list.Element
47
        candidates    map[wtdb.TowerID]*Tower
48
}
49

50
// Compile-time constraint to ensure *towerListIterator implements the
51
// TowerCandidateIterator interface.
52
var _ TowerCandidateIterator = (*towerListIterator)(nil)
53

54
// newTowerListIterator initializes a new towerListIterator from a variadic list
55
// of lnwire.NetAddresses.
56
func newTowerListIterator(candidates ...*Tower) *towerListIterator {
37✔
57
        iter := &towerListIterator{
37✔
58
                queue:      list.New(),
37✔
59
                candidates: make(map[wtdb.TowerID]*Tower),
37✔
60
        }
37✔
61

37✔
62
        for _, candidate := range candidates {
41✔
63
                iter.queue.PushBack(candidate.ID)
4✔
64
                iter.candidates[candidate.ID] = candidate
4✔
65
        }
4✔
66
        iter.Reset()
37✔
67

37✔
68
        return iter
37✔
69
}
70

71
// Reset clears the iterators state, and makes the address at the front of the
72
// list the next item to be returned..
73
func (t *towerListIterator) Reset() error {
168✔
74
        t.mu.Lock()
168✔
75
        defer t.mu.Unlock()
168✔
76

168✔
77
        // Reset the next candidate to the front of the linked-list.
168✔
78
        t.nextCandidate = t.queue.Front()
168✔
79

168✔
80
        return nil
168✔
81
}
168✔
82

83
// GetTower gets the tower with the given ID from the iterator. If no such tower
84
// is found then ErrTowerNotInIterator is returned.
85
func (t *towerListIterator) GetTower(id wtdb.TowerID) (*Tower, error) {
6✔
86
        t.mu.Lock()
6✔
87
        defer t.mu.Unlock()
6✔
88

6✔
89
        tower, ok := t.candidates[id]
6✔
90
        if !ok {
7✔
91
                return nil, ErrTowerNotInIterator
1✔
92
        }
1✔
93

94
        return tower, nil
5✔
95
}
96

97
// Next returns the next candidate tower. This iterator will always return
98
// candidates in the order given when the iterator was instantiated.  If no more
99
// candidates are available, ErrTowerCandidatesExhausted is returned.
100
func (t *towerListIterator) Next() (*Tower, error) {
251✔
101
        t.mu.Lock()
251✔
102
        defer t.mu.Unlock()
251✔
103

251✔
104
        for t.nextCandidate != nil {
377✔
105
                // Propose the tower at the front of the list.
126✔
106
                towerID := t.nextCandidate.Value.(wtdb.TowerID)
126✔
107

126✔
108
                // Check whether this tower is still considered a candidate. If
126✔
109
                // it's not, we'll proceed to the next.
126✔
110
                tower, ok := t.candidates[towerID]
126✔
111
                if !ok {
132✔
112
                        nextCandidate := t.nextCandidate.Next()
6✔
113
                        t.queue.Remove(t.nextCandidate)
6✔
114
                        t.nextCandidate = nextCandidate
6✔
115
                        continue
6✔
116
                }
117

118
                // Set the next candidate to the subsequent element.
119
                t.nextCandidate = t.nextCandidate.Next()
120✔
120
                return tower, nil
120✔
121
        }
122

123
        return nil, ErrTowerCandidatesExhausted
131✔
124
}
125

126
// AddCandidate adds a new candidate tower to the iterator. If the candidate
127
// already exists, then any new addresses are added to it.
128
func (t *towerListIterator) AddCandidate(candidate *Tower) {
58✔
129
        t.mu.Lock()
58✔
130
        defer t.mu.Unlock()
58✔
131

58✔
132
        if tower, ok := t.candidates[candidate.ID]; !ok {
104✔
133
                t.queue.PushBack(candidate.ID)
46✔
134
                t.candidates[candidate.ID] = candidate
46✔
135

46✔
136
                // If we've reached the end of our queue, then this candidate
46✔
137
                // will become the next.
46✔
138
                if t.nextCandidate == nil {
90✔
139
                        t.nextCandidate = t.queue.Back()
44✔
140
                }
44✔
141
        } else {
12✔
142
                candidate.Addresses.Reset()
12✔
143
                firstAddr := candidate.Addresses.Peek()
12✔
144
                tower.Addresses.Add(firstAddr)
12✔
145
                for {
27✔
146
                        next, err := candidate.Addresses.Next()
15✔
147
                        if err != nil {
27✔
148
                                candidate.Addresses.Reset()
12✔
149
                                break
12✔
150
                        }
151

152
                        tower.Addresses.Add(next)
3✔
153
                }
154
        }
155
}
156

157
// RemoveCandidate removes an existing candidate tower from the iterator. An
158
// optional address can be provided to indicate a stale tower address to remove
159
// it. If it isn't provided, then the tower is completely removed from the
160
// iterator.
161
func (t *towerListIterator) RemoveCandidate(candidate wtdb.TowerID,
162
        addr net.Addr) error {
16✔
163

16✔
164
        t.mu.Lock()
16✔
165
        defer t.mu.Unlock()
16✔
166

16✔
167
        tower, ok := t.candidates[candidate]
16✔
168
        if !ok {
16✔
UNCOV
169
                return nil
×
UNCOV
170
        }
×
171
        if addr != nil {
20✔
172
                err := tower.Addresses.Remove(addr)
4✔
173
                if err != nil {
6✔
174
                        return err
2✔
175
                }
2✔
176
        } else {
12✔
177
                if tower.Addresses.HasLocked() {
12✔
178
                        return ErrAddrInUse
×
179
                }
×
180

181
                delete(t.candidates, candidate)
12✔
182
        }
183

184
        return nil
14✔
185
}
186

187
// IsActive determines whether a given tower is exists within the iterator.
188
func (t *towerListIterator) IsActive(tower wtdb.TowerID) bool {
15✔
189
        t.mu.Lock()
15✔
190
        defer t.mu.Unlock()
15✔
191

15✔
192
        _, ok := t.candidates[tower]
15✔
193
        return ok
15✔
194
}
15✔
195

196
// TODO(conner): implement graph-backed candidate iterator for public towers.
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