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

lightningnetwork / lnd / 13593508312

28 Feb 2025 05:41PM UTC coverage: 58.287% (-10.4%) from 68.65%
13593508312

Pull #9458

github

web-flow
Merge d40067c0c into f1182e433
Pull Request #9458: multi+server.go: add initial permissions for some peers

346 of 548 new or added lines in 10 files covered. (63.14%)

27412 existing lines in 442 files now uncovered.

94709 of 162488 relevant lines covered (58.29%)

1.81 hits per line

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

0.0
/sweep/test_utils.go
1
package sweep
2

3
import (
4
        "fmt"
5
        "sync"
6
        "testing"
7
        "time"
8

9
        "github.com/btcsuite/btcd/chaincfg/chainhash"
10
        "github.com/btcsuite/btcd/wire"
11
        "github.com/lightningnetwork/lnd/chainntnfs"
12
)
13

14
var (
15
        defaultTestTimeout = 5 * time.Second
16
        processingDelay    = 1 * time.Second
17
        mockChainHash, _   = chainhash.NewHashFromStr("00aabbccddeeff")
18
        mockChainHeight    = int32(100)
19
)
20

21
// MockNotifier simulates the chain notifier for test purposes. This type is
22
// exported because it is used in nursery tests.
23
type MockNotifier struct {
24
        confChannel map[chainhash.Hash]chan *chainntnfs.TxConfirmation
25
        epochChan   map[chan *chainntnfs.BlockEpoch]int32
26
        spendChan   map[wire.OutPoint][]chan *chainntnfs.SpendDetail
27
        spends      map[wire.OutPoint]*wire.MsgTx
28
        mutex       sync.RWMutex
29
        t           *testing.T
30
}
31

32
// NewMockNotifier instantiates a new mock notifier.
UNCOV
33
func NewMockNotifier(t *testing.T) *MockNotifier {
×
UNCOV
34
        return &MockNotifier{
×
UNCOV
35
                confChannel: make(map[chainhash.Hash]chan *chainntnfs.TxConfirmation),
×
UNCOV
36
                epochChan:   make(map[chan *chainntnfs.BlockEpoch]int32),
×
UNCOV
37
                spendChan:   make(map[wire.OutPoint][]chan *chainntnfs.SpendDetail),
×
UNCOV
38
                spends:      make(map[wire.OutPoint]*wire.MsgTx),
×
UNCOV
39
                t:           t,
×
UNCOV
40
        }
×
UNCOV
41
}
×
42

43
// NotifyEpochNonBlocking simulates a new epoch arriving without blocking when
44
// the epochChan is not read.
45
func (m *MockNotifier) NotifyEpochNonBlocking(height int32) {
×
46
        m.t.Helper()
×
47

×
48
        for epochChan, chanHeight := range m.epochChan {
×
49
                // Only send notifications if the height is greater than the
×
50
                // height the caller passed into the register call.
×
51
                if chanHeight >= height {
×
52
                        continue
×
53
                }
54

55
                log.Debugf("Notifying height %v to listener", height)
×
56

×
57
                select {
×
58
                case epochChan <- &chainntnfs.BlockEpoch{Height: height}:
×
59
                default:
×
60
                }
61
        }
62
}
63

64
// NotifyEpoch simulates a new epoch arriving.
UNCOV
65
func (m *MockNotifier) NotifyEpoch(height int32) {
×
UNCOV
66
        m.t.Helper()
×
UNCOV
67

×
UNCOV
68
        for epochChan, chanHeight := range m.epochChan {
×
UNCOV
69
                // Only send notifications if the height is greater than the
×
UNCOV
70
                // height the caller passed into the register call.
×
UNCOV
71
                if chanHeight >= height {
×
72
                        continue
×
73
                }
74

UNCOV
75
                log.Debugf("Notifying height %v to listener", height)
×
UNCOV
76

×
UNCOV
77
                select {
×
78
                case epochChan <- &chainntnfs.BlockEpoch{
79
                        Height: height,
UNCOV
80
                }:
×
81
                case <-time.After(defaultTestTimeout):
×
82
                        m.t.Fatal("epoch event not consumed")
×
83
                }
84
        }
85
}
86

87
// ConfirmTx simulates a tx confirming.
UNCOV
88
func (m *MockNotifier) ConfirmTx(txid *chainhash.Hash, height uint32) error {
×
UNCOV
89
        confirm := &chainntnfs.TxConfirmation{
×
UNCOV
90
                BlockHeight: height,
×
UNCOV
91
        }
×
UNCOV
92
        select {
×
UNCOV
93
        case m.getConfChannel(txid) <- confirm:
×
94
        case <-time.After(defaultTestTimeout):
×
95
                return fmt.Errorf("confirmation not consumed")
×
96
        }
UNCOV
97
        return nil
×
98
}
99

100
// SpendOutpoint simulates a utxo being spent.
101
func (m *MockNotifier) SpendOutpoint(outpoint wire.OutPoint,
102
        spendingTx wire.MsgTx) {
×
103

×
104
        log.Debugf("Spending outpoint %v", outpoint)
×
105

×
106
        m.mutex.Lock()
×
107
        defer m.mutex.Unlock()
×
108

×
109
        channels, ok := m.spendChan[outpoint]
×
110
        if ok {
×
111
                for _, channel := range channels {
×
112
                        m.sendSpend(channel, &outpoint, &spendingTx)
×
113
                }
×
114
        }
115

116
        m.spends[outpoint] = &spendingTx
×
117
}
118

119
func (m *MockNotifier) sendSpend(channel chan *chainntnfs.SpendDetail,
120
        outpoint *wire.OutPoint,
121
        spendingTx *wire.MsgTx) {
×
122

×
123
        log.Debugf("Notifying spend of outpoint %v", outpoint)
×
124

×
125
        spenderTxHash := spendingTx.TxHash()
×
126
        channel <- &chainntnfs.SpendDetail{
×
127
                SpenderTxHash: &spenderTxHash,
×
128
                SpendingTx:    spendingTx,
×
129
                SpentOutPoint: outpoint,
×
130
        }
×
131
}
×
132

133
// RegisterConfirmationsNtfn registers for tx confirm notifications.
134
func (m *MockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
135
        _ []byte, numConfs, heightHint uint32,
UNCOV
136
        opt ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
×
UNCOV
137

×
UNCOV
138
        return &chainntnfs.ConfirmationEvent{
×
UNCOV
139
                Confirmed: m.getConfChannel(txid),
×
UNCOV
140
        }, nil
×
UNCOV
141
}
×
142

143
func (m *MockNotifier) getConfChannel(
UNCOV
144
        txid *chainhash.Hash) chan *chainntnfs.TxConfirmation {
×
UNCOV
145

×
UNCOV
146
        m.mutex.Lock()
×
UNCOV
147
        defer m.mutex.Unlock()
×
UNCOV
148

×
UNCOV
149
        channel, ok := m.confChannel[*txid]
×
UNCOV
150
        if ok {
×
UNCOV
151
                return channel
×
UNCOV
152
        }
×
UNCOV
153
        channel = make(chan *chainntnfs.TxConfirmation)
×
UNCOV
154
        m.confChannel[*txid] = channel
×
UNCOV
155

×
UNCOV
156
        return channel
×
157
}
158

159
// RegisterBlockEpochNtfn registers a block notification.
160
func (m *MockNotifier) RegisterBlockEpochNtfn(
UNCOV
161
        bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, error) {
×
UNCOV
162

×
UNCOV
163
        log.Tracef("Mock block ntfn registered")
×
UNCOV
164

×
UNCOV
165
        m.mutex.Lock()
×
UNCOV
166
        epochChan := make(chan *chainntnfs.BlockEpoch, 1)
×
UNCOV
167

×
UNCOV
168
        // The real notifier returns a notification with the current block hash
×
UNCOV
169
        // and height immediately if no best block hash or height is specified
×
UNCOV
170
        // in the request. We want to emulate this behaviour as well for the
×
UNCOV
171
        // mock.
×
UNCOV
172
        switch {
×
173
        case bestBlock == nil:
×
174
                epochChan <- &chainntnfs.BlockEpoch{
×
175
                        Hash:   mockChainHash,
×
176
                        Height: mockChainHeight,
×
177
                }
×
178
                m.epochChan[epochChan] = mockChainHeight
×
UNCOV
179
        default:
×
UNCOV
180
                m.epochChan[epochChan] = bestBlock.Height
×
181
        }
UNCOV
182
        m.mutex.Unlock()
×
UNCOV
183

×
UNCOV
184
        return &chainntnfs.BlockEpochEvent{
×
UNCOV
185
                Epochs: epochChan,
×
UNCOV
186
                Cancel: func() {
×
UNCOV
187
                        log.Tracef("Mock block ntfn canceled")
×
UNCOV
188
                        m.mutex.Lock()
×
UNCOV
189
                        delete(m.epochChan, epochChan)
×
UNCOV
190
                        m.mutex.Unlock()
×
UNCOV
191
                },
×
192
        }, nil
193
}
194

195
// Start the notifier.
196
func (m *MockNotifier) Start() error {
×
197
        return nil
×
198
}
×
199

200
// Started checks if started.
201
func (m *MockNotifier) Started() bool {
×
202
        return true
×
203
}
×
204

205
// Stop the notifier.
206
func (m *MockNotifier) Stop() error {
×
207
        return nil
×
208
}
×
209

210
// RegisterSpendNtfn registers for spend notifications.
211
func (m *MockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
212
        _ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
×
213

×
214
        log.Debugf("RegisterSpendNtfn for outpoint %v", outpoint)
×
215

×
216
        // Add channel to global spend ntfn map.
×
217
        m.mutex.Lock()
×
218

×
219
        channels, ok := m.spendChan[*outpoint]
×
220
        if !ok {
×
221
                channels = make([]chan *chainntnfs.SpendDetail, 0)
×
222
        }
×
223

224
        channel := make(chan *chainntnfs.SpendDetail, 1)
×
225
        channels = append(channels, channel)
×
226
        m.spendChan[*outpoint] = channels
×
227

×
228
        // Check if this output has already been spent.
×
229
        spendingTx, spent := m.spends[*outpoint]
×
230

×
231
        m.mutex.Unlock()
×
232

×
233
        // If output has been spent already, signal now. Do this outside the
×
234
        // lock to prevent a deadlock.
×
235
        if spent {
×
236
                m.sendSpend(channel, outpoint, spendingTx)
×
237
        }
×
238

239
        return &chainntnfs.SpendEvent{
×
240
                Spend: channel,
×
241
                Cancel: func() {
×
242
                        log.Infof("Cancelling RegisterSpendNtfn for %v",
×
243
                                outpoint)
×
244

×
245
                        m.mutex.Lock()
×
246
                        defer m.mutex.Unlock()
×
247
                        channels := m.spendChan[*outpoint]
×
248
                        for i, c := range channels {
×
249
                                if c == channel {
×
250
                                        channels[i] = channels[len(channels)-1]
×
251
                                        m.spendChan[*outpoint] =
×
252
                                                channels[:len(channels)-1]
×
253
                                }
×
254
                        }
255

256
                        close(channel)
×
257

×
258
                        log.Infof("Spend ntfn channel closed for %v",
×
259
                                outpoint)
×
260
                },
261
        }, nil
262
}
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