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

lightningnetwork / lnd / 17777197509

16 Sep 2025 07:46PM UTC coverage: 57.202% (-9.5%) from 66.657%
17777197509

Pull #9489

github

web-flow
Merge bd2ae0bae into cbed86e21
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

329 of 564 new or added lines in 12 files covered. (58.33%)

28576 existing lines in 457 files now uncovered.

99724 of 174338 relevant lines covered (57.2%)

1.78 hits per line

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

0.0
/peer/test_utils.go
1
package peer
2

3
import (
4
        "bytes"
5
        crand "crypto/rand"
6
        "encoding/binary"
7
        "io"
8
        "math/rand"
9
        "net"
10
        "sync/atomic"
11
        "testing"
12
        "time"
13

14
        "github.com/btcsuite/btcd/btcec/v2"
15
        "github.com/btcsuite/btcd/btcutil"
16
        "github.com/btcsuite/btcd/chaincfg/chainhash"
17
        "github.com/btcsuite/btcd/wire"
18
        "github.com/lightningnetwork/lnd/chainntnfs"
19
        "github.com/lightningnetwork/lnd/channeldb"
20
        "github.com/lightningnetwork/lnd/channelnotifier"
21
        "github.com/lightningnetwork/lnd/fn/v2"
22
        graphdb "github.com/lightningnetwork/lnd/graph/db"
23
        "github.com/lightningnetwork/lnd/htlcswitch"
24
        "github.com/lightningnetwork/lnd/input"
25
        "github.com/lightningnetwork/lnd/keychain"
26
        "github.com/lightningnetwork/lnd/lntest/channels"
27
        "github.com/lightningnetwork/lnd/lntest/mock"
28
        "github.com/lightningnetwork/lnd/lntypes"
29
        "github.com/lightningnetwork/lnd/lnwallet"
30
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
31
        "github.com/lightningnetwork/lnd/lnwire"
32
        "github.com/lightningnetwork/lnd/netann"
33
        "github.com/lightningnetwork/lnd/pool"
34
        "github.com/lightningnetwork/lnd/queue"
35
        "github.com/lightningnetwork/lnd/shachain"
36
        "github.com/stretchr/testify/require"
37
)
38

39
const (
40
        broadcastHeight = 100
41

42
        // timeout is a timeout value to use for tests which need to wait for
43
        // a return value on a channel.
44
        timeout = time.Second * 5
45

46
        // testCltvRejectDelta is the minimum delta between expiry and current
47
        // height below which htlcs are rejected.
48
        testCltvRejectDelta = 13
49
)
50

51
var (
52
        testKeyLoc = keychain.KeyLocator{Family: keychain.KeyFamilyNodeKey}
53
)
54

55
// noUpdate is a function which can be used as a parameter in
56
// createTestPeerWithChannel to call the setup code with no custom values on
57
// the channels set up.
UNCOV
58
var noUpdate = func(a, b *channeldb.OpenChannel) {}
×
59

60
type peerTestCtx struct {
61
        peer          *Brontide
62
        channel       *lnwallet.LightningChannel
63
        notifier      *mock.ChainNotifier
64
        publishTx     <-chan *wire.MsgTx
65
        mockSwitch    *mockMessageSwitch
66
        db            *channeldb.DB
67
        privKey       *btcec.PrivateKey
68
        mockConn      *mockMessageConn
69
        customChan    chan *customMsg
70
        chanStatusMgr *netann.ChanStatusManager
71
}
72

73
// createTestPeerWithChannel creates a channel between two nodes, and returns a
74
// peer for one of the nodes, together with the channel seen from both nodes.
75
// It takes an updateChan function which can be used to modify the default
76
// values on the channel states for each peer.
77
func createTestPeerWithChannel(t *testing.T, updateChan func(a,
UNCOV
78
        b *channeldb.OpenChannel)) (*peerTestCtx, error) {
×
UNCOV
79

×
UNCOV
80
        params := createTestPeer(t)
×
UNCOV
81

×
UNCOV
82
        var (
×
UNCOV
83
                publishTx     = params.publishTx
×
UNCOV
84
                mockSwitch    = params.mockSwitch
×
UNCOV
85
                alicePeer     = params.peer
×
UNCOV
86
                notifier      = params.notifier
×
UNCOV
87
                aliceKeyPriv  = params.privKey
×
UNCOV
88
                dbAlice       = params.db
×
UNCOV
89
                chanStatusMgr = params.chanStatusMgr
×
UNCOV
90
        )
×
UNCOV
91

×
UNCOV
92
        err := chanStatusMgr.Start()
×
UNCOV
93
        require.NoError(t, err)
×
UNCOV
94
        t.Cleanup(func() {
×
UNCOV
95
                require.NoError(t, chanStatusMgr.Stop())
×
UNCOV
96
        })
×
97

UNCOV
98
        aliceKeyPub := alicePeer.IdentityKey()
×
UNCOV
99
        estimator := alicePeer.cfg.FeeEstimator
×
UNCOV
100

×
UNCOV
101
        channelCapacity := btcutil.Amount(10 * 1e8)
×
UNCOV
102
        channelBal := channelCapacity / 2
×
UNCOV
103
        aliceDustLimit := btcutil.Amount(200)
×
UNCOV
104
        bobDustLimit := btcutil.Amount(1300)
×
UNCOV
105
        csvTimeoutAlice := uint32(5)
×
UNCOV
106
        csvTimeoutBob := uint32(4)
×
UNCOV
107
        isAliceInitiator := true
×
UNCOV
108

×
UNCOV
109
        prevOut := &wire.OutPoint{
×
UNCOV
110
                Hash:  channels.TestHdSeed,
×
UNCOV
111
                Index: 0,
×
UNCOV
112
        }
×
UNCOV
113
        fundingTxIn := wire.NewTxIn(prevOut, nil, nil)
×
UNCOV
114

×
UNCOV
115
        bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(
×
UNCOV
116
                channels.BobsPrivKey,
×
UNCOV
117
        )
×
UNCOV
118

×
UNCOV
119
        aliceCfg := channeldb.ChannelConfig{
×
UNCOV
120
                ChannelStateBounds: channeldb.ChannelStateBounds{
×
UNCOV
121
                        MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
×
UNCOV
122
                        ChanReserve:      btcutil.Amount(rand.Int63()),
×
UNCOV
123
                        MinHTLC:          lnwire.MilliSatoshi(rand.Int63()),
×
UNCOV
124
                        MaxAcceptedHtlcs: uint16(rand.Int31()),
×
UNCOV
125
                },
×
UNCOV
126
                CommitmentParams: channeldb.CommitmentParams{
×
UNCOV
127
                        DustLimit: aliceDustLimit,
×
UNCOV
128
                        CsvDelay:  uint16(csvTimeoutAlice),
×
UNCOV
129
                },
×
UNCOV
130
                MultiSigKey: keychain.KeyDescriptor{
×
UNCOV
131
                        PubKey: aliceKeyPub,
×
UNCOV
132
                },
×
UNCOV
133
                RevocationBasePoint: keychain.KeyDescriptor{
×
UNCOV
134
                        PubKey: aliceKeyPub,
×
UNCOV
135
                },
×
UNCOV
136
                PaymentBasePoint: keychain.KeyDescriptor{
×
UNCOV
137
                        PubKey: aliceKeyPub,
×
UNCOV
138
                },
×
UNCOV
139
                DelayBasePoint: keychain.KeyDescriptor{
×
UNCOV
140
                        PubKey: aliceKeyPub,
×
UNCOV
141
                },
×
UNCOV
142
                HtlcBasePoint: keychain.KeyDescriptor{
×
UNCOV
143
                        PubKey: aliceKeyPub,
×
UNCOV
144
                },
×
UNCOV
145
        }
×
UNCOV
146
        bobCfg := channeldb.ChannelConfig{
×
UNCOV
147
                ChannelStateBounds: channeldb.ChannelStateBounds{
×
UNCOV
148
                        MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
×
UNCOV
149
                        ChanReserve:      btcutil.Amount(rand.Int63()),
×
UNCOV
150
                        MinHTLC:          lnwire.MilliSatoshi(rand.Int63()),
×
UNCOV
151
                        MaxAcceptedHtlcs: uint16(rand.Int31()),
×
UNCOV
152
                },
×
UNCOV
153
                CommitmentParams: channeldb.CommitmentParams{
×
UNCOV
154
                        DustLimit: bobDustLimit,
×
UNCOV
155
                        CsvDelay:  uint16(csvTimeoutBob),
×
UNCOV
156
                },
×
UNCOV
157
                MultiSigKey: keychain.KeyDescriptor{
×
UNCOV
158
                        PubKey: bobKeyPub,
×
UNCOV
159
                },
×
UNCOV
160
                RevocationBasePoint: keychain.KeyDescriptor{
×
UNCOV
161
                        PubKey: bobKeyPub,
×
UNCOV
162
                },
×
UNCOV
163
                PaymentBasePoint: keychain.KeyDescriptor{
×
UNCOV
164
                        PubKey: bobKeyPub,
×
UNCOV
165
                },
×
UNCOV
166
                DelayBasePoint: keychain.KeyDescriptor{
×
UNCOV
167
                        PubKey: bobKeyPub,
×
UNCOV
168
                },
×
UNCOV
169
                HtlcBasePoint: keychain.KeyDescriptor{
×
UNCOV
170
                        PubKey: bobKeyPub,
×
UNCOV
171
                },
×
UNCOV
172
        }
×
UNCOV
173

×
UNCOV
174
        bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize())
×
UNCOV
175
        if err != nil {
×
176
                return nil, err
×
177
        }
×
UNCOV
178
        bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot)
×
UNCOV
179
        bobFirstRevoke, err := bobPreimageProducer.AtIndex(0)
×
UNCOV
180
        if err != nil {
×
181
                return nil, err
×
182
        }
×
UNCOV
183
        bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
×
UNCOV
184

×
UNCOV
185
        aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
×
UNCOV
186
        if err != nil {
×
187
                return nil, err
×
188
        }
×
UNCOV
189
        alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot)
×
UNCOV
190
        aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0)
×
UNCOV
191
        if err != nil {
×
192
                return nil, err
×
193
        }
×
UNCOV
194
        aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
×
UNCOV
195

×
UNCOV
196
        aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(
×
UNCOV
197
                channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
×
UNCOV
198
                bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,
×
UNCOV
199
                isAliceInitiator, 0,
×
UNCOV
200
        )
×
UNCOV
201
        if err != nil {
×
202
                return nil, err
×
203
        }
×
204

UNCOV
205
        dbBob := channeldb.OpenForTesting(t, t.TempDir())
×
UNCOV
206

×
UNCOV
207
        feePerKw, err := estimator.EstimateFeePerKW(1)
×
UNCOV
208
        if err != nil {
×
209
                return nil, err
×
210
        }
×
211

212
        // TODO(roasbeef): need to factor in commit fee?
UNCOV
213
        aliceCommit := channeldb.ChannelCommitment{
×
UNCOV
214
                CommitHeight:  0,
×
UNCOV
215
                LocalBalance:  lnwire.NewMSatFromSatoshis(channelBal),
×
UNCOV
216
                RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
×
UNCOV
217
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
218
                CommitFee:     feePerKw.FeeForWeight(input.CommitWeight),
×
UNCOV
219
                CommitTx:      aliceCommitTx,
×
UNCOV
220
                CommitSig:     bytes.Repeat([]byte{1}, 71),
×
UNCOV
221
        }
×
UNCOV
222
        bobCommit := channeldb.ChannelCommitment{
×
UNCOV
223
                CommitHeight:  0,
×
UNCOV
224
                LocalBalance:  lnwire.NewMSatFromSatoshis(channelBal),
×
UNCOV
225
                RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
×
UNCOV
226
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
227
                CommitFee:     feePerKw.FeeForWeight(input.CommitWeight),
×
UNCOV
228
                CommitTx:      bobCommitTx,
×
UNCOV
229
                CommitSig:     bytes.Repeat([]byte{1}, 71),
×
UNCOV
230
        }
×
UNCOV
231

×
UNCOV
232
        var chanIDBytes [8]byte
×
UNCOV
233
        if _, err := io.ReadFull(crand.Reader, chanIDBytes[:]); err != nil {
×
234
                return nil, err
×
235
        }
×
236

UNCOV
237
        shortChanID := lnwire.NewShortChanIDFromInt(
×
UNCOV
238
                binary.BigEndian.Uint64(chanIDBytes[:]),
×
UNCOV
239
        )
×
UNCOV
240

×
UNCOV
241
        aliceChannelState := &channeldb.OpenChannel{
×
UNCOV
242
                LocalChanCfg:            aliceCfg,
×
UNCOV
243
                RemoteChanCfg:           bobCfg,
×
UNCOV
244
                IdentityPub:             aliceKeyPub,
×
UNCOV
245
                FundingOutpoint:         *prevOut,
×
UNCOV
246
                ShortChannelID:          shortChanID,
×
UNCOV
247
                ChanType:                channeldb.SingleFunderTweaklessBit,
×
UNCOV
248
                IsInitiator:             isAliceInitiator,
×
UNCOV
249
                Capacity:                channelCapacity,
×
UNCOV
250
                RemoteCurrentRevocation: bobCommitPoint,
×
UNCOV
251
                RevocationProducer:      alicePreimageProducer,
×
UNCOV
252
                RevocationStore:         shachain.NewRevocationStore(),
×
UNCOV
253
                LocalCommitment:         aliceCommit,
×
UNCOV
254
                RemoteCommitment:        aliceCommit,
×
UNCOV
255
                Db:                      dbAlice.ChannelStateDB(),
×
UNCOV
256
                Packager:                channeldb.NewChannelPackager(shortChanID),
×
UNCOV
257
                FundingTxn:              channels.TestFundingTx,
×
UNCOV
258
        }
×
UNCOV
259
        bobChannelState := &channeldb.OpenChannel{
×
UNCOV
260
                LocalChanCfg:            bobCfg,
×
UNCOV
261
                RemoteChanCfg:           aliceCfg,
×
UNCOV
262
                IdentityPub:             bobKeyPub,
×
UNCOV
263
                FundingOutpoint:         *prevOut,
×
UNCOV
264
                ChanType:                channeldb.SingleFunderTweaklessBit,
×
UNCOV
265
                IsInitiator:             !isAliceInitiator,
×
UNCOV
266
                Capacity:                channelCapacity,
×
UNCOV
267
                RemoteCurrentRevocation: aliceCommitPoint,
×
UNCOV
268
                RevocationProducer:      bobPreimageProducer,
×
UNCOV
269
                RevocationStore:         shachain.NewRevocationStore(),
×
UNCOV
270
                LocalCommitment:         bobCommit,
×
UNCOV
271
                RemoteCommitment:        bobCommit,
×
UNCOV
272
                Db:                      dbBob.ChannelStateDB(),
×
UNCOV
273
                Packager:                channeldb.NewChannelPackager(shortChanID),
×
UNCOV
274
        }
×
UNCOV
275

×
UNCOV
276
        // Set custom values on the channel states.
×
UNCOV
277
        updateChan(aliceChannelState, bobChannelState)
×
UNCOV
278

×
UNCOV
279
        aliceAddr := alicePeer.cfg.Addr.Address
×
UNCOV
280
        if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil {
×
281
                return nil, err
×
282
        }
×
283

UNCOV
284
        bobAddr := &net.TCPAddr{
×
UNCOV
285
                IP:   net.ParseIP("127.0.0.1"),
×
UNCOV
286
                Port: 18556,
×
UNCOV
287
        }
×
UNCOV
288

×
UNCOV
289
        if err := bobChannelState.SyncPending(bobAddr, 0); err != nil {
×
290
                return nil, err
×
291
        }
×
292

UNCOV
293
        aliceSigner := input.NewMockSigner(
×
UNCOV
294
                []*btcec.PrivateKey{aliceKeyPriv}, nil,
×
UNCOV
295
        )
×
UNCOV
296
        bobSigner := input.NewMockSigner(
×
UNCOV
297
                []*btcec.PrivateKey{bobKeyPriv}, nil,
×
UNCOV
298
        )
×
UNCOV
299

×
UNCOV
300
        alicePool := lnwallet.NewSigPool(1, aliceSigner)
×
UNCOV
301
        channelAlice, err := lnwallet.NewLightningChannel(
×
UNCOV
302
                aliceSigner, aliceChannelState, alicePool,
×
UNCOV
303
                lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}),
×
UNCOV
304
                lnwallet.WithAuxSigner(lnwallet.NewAuxSignerMock(
×
UNCOV
305
                        lnwallet.EmptyMockJobHandler,
×
UNCOV
306
                )),
×
UNCOV
307
        )
×
UNCOV
308
        if err != nil {
×
309
                return nil, err
×
310
        }
×
UNCOV
311
        _ = alicePool.Start()
×
UNCOV
312
        t.Cleanup(func() {
×
UNCOV
313
                require.NoError(t, alicePool.Stop())
×
UNCOV
314
        })
×
315

UNCOV
316
        bobPool := lnwallet.NewSigPool(1, bobSigner)
×
UNCOV
317
        channelBob, err := lnwallet.NewLightningChannel(
×
UNCOV
318
                bobSigner, bobChannelState, bobPool,
×
UNCOV
319
                lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}),
×
UNCOV
320
                lnwallet.WithAuxSigner(lnwallet.NewAuxSignerMock(
×
UNCOV
321
                        lnwallet.EmptyMockJobHandler,
×
UNCOV
322
                )),
×
UNCOV
323
        )
×
UNCOV
324
        if err != nil {
×
325
                return nil, err
×
326
        }
×
UNCOV
327
        _ = bobPool.Start()
×
UNCOV
328
        t.Cleanup(func() {
×
UNCOV
329
                require.NoError(t, bobPool.Stop())
×
UNCOV
330
        })
×
331

UNCOV
332
        alicePeer.remoteFeatures = lnwire.NewFeatureVector(
×
UNCOV
333
                nil, lnwire.Features,
×
UNCOV
334
        )
×
UNCOV
335

×
UNCOV
336
        chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint())
×
UNCOV
337
        alicePeer.activeChannels.Store(chanID, channelAlice)
×
UNCOV
338

×
UNCOV
339
        alicePeer.cg.WgAdd(1)
×
UNCOV
340
        go alicePeer.channelManager()
×
UNCOV
341

×
UNCOV
342
        return &peerTestCtx{
×
UNCOV
343
                peer:       alicePeer,
×
UNCOV
344
                channel:    channelBob,
×
UNCOV
345
                notifier:   notifier,
×
UNCOV
346
                publishTx:  publishTx,
×
UNCOV
347
                mockSwitch: mockSwitch,
×
UNCOV
348
                mockConn:   params.mockConn,
×
UNCOV
349
        }, nil
×
350
}
351

352
// mockMessageSwitch is a mock implementation of the messageSwitch interface
353
// used for testing without relying on a *htlcswitch.Switch in unit tests.
354
type mockMessageSwitch struct {
355
        links []htlcswitch.ChannelUpdateHandler
356
}
357

358
// BestHeight currently returns a dummy value.
359
func (m *mockMessageSwitch) BestHeight() uint32 {
×
360
        return 0
×
361
}
×
362

363
// CircuitModifier currently returns a dummy value.
364
func (m *mockMessageSwitch) CircuitModifier() htlcswitch.CircuitModifier {
×
365
        return nil
×
366
}
×
367

368
// RemoveLink currently does nothing.
UNCOV
369
func (m *mockMessageSwitch) RemoveLink(cid lnwire.ChannelID) {}
×
370

371
// CreateAndAddLink currently returns a dummy value.
372
func (m *mockMessageSwitch) CreateAndAddLink(cfg htlcswitch.ChannelLinkConfig,
373
        lnChan *lnwallet.LightningChannel) error {
×
374

×
375
        return nil
×
376
}
×
377

378
// GetLinksByInterface returns the active links.
379
func (m *mockMessageSwitch) GetLinksByInterface(pub [33]byte) (
UNCOV
380
        []htlcswitch.ChannelUpdateHandler, error) {
×
UNCOV
381

×
UNCOV
382
        return m.links, nil
×
UNCOV
383
}
×
384

385
// mockUpdateHandler is a mock implementation of the ChannelUpdateHandler
386
// interface. It is used in mockMessageSwitch's GetLinksByInterface method.
387
type mockUpdateHandler struct {
388
        cid                  lnwire.ChannelID
389
        isOutgoingAddBlocked atomic.Bool
390
        isIncomingAddBlocked atomic.Bool
391
}
392

393
// newMockUpdateHandler creates a new mockUpdateHandler.
UNCOV
394
func newMockUpdateHandler(cid lnwire.ChannelID) *mockUpdateHandler {
×
UNCOV
395
        return &mockUpdateHandler{
×
UNCOV
396
                cid: cid,
×
UNCOV
397
        }
×
UNCOV
398
}
×
399

400
// HandleChannelUpdate currently does nothing.
401
func (m *mockUpdateHandler) HandleChannelUpdate(msg lnwire.Message) {}
×
402

403
// ChanID returns the mockUpdateHandler's cid.
UNCOV
404
func (m *mockUpdateHandler) ChanID() lnwire.ChannelID { return m.cid }
×
405

406
// ShortChanID returns the mockUpdateHandler's cid.
NEW
407
func (m *mockUpdateHandler) ShortChanID() lnwire.ShortChannelID {
×
NEW
408
        return lnwire.NewShortChanIDFromInt(0)
×
NEW
409
}
×
410

411
// Bandwidth currently returns a dummy value.
412
func (m *mockUpdateHandler) Bandwidth() lnwire.MilliSatoshi { return 0 }
×
413

414
// EligibleToForward currently returns a dummy value.
415
func (m *mockUpdateHandler) EligibleToForward() bool { return false }
×
416

417
// MayAddOutgoingHtlc currently returns nil.
418
func (m *mockUpdateHandler) MayAddOutgoingHtlc(lnwire.MilliSatoshi) error { return nil }
×
419

420
type mockMessageConn struct {
421
        t *testing.T
422

423
        // MessageConn embeds our interface so that the mock does not need to
424
        // implement every function. The mock will panic if an unspecified function
425
        // is called.
426
        MessageConn
427

428
        // writtenMessages is a channel that our mock pushes written messages into.
429
        writtenMessages chan []byte
430

431
        readMessages   chan []byte
432
        curReadMessage []byte
433

434
        // writeRaceDetectingCounter is incremented on any function call
435
        // associated with writing to the connection. The race detector will
436
        // trigger on this counter if a data race exists.
437
        writeRaceDetectingCounter int
438

439
        // readRaceDetectingCounter is incremented on any function call
440
        // associated with reading from the connection. The race detector will
441
        // trigger on this counter if a data race exists.
442
        readRaceDetectingCounter int
443
}
444

445
func (m *mockUpdateHandler) EnableAdds(dir htlcswitch.LinkDirection) bool {
×
446
        if dir == htlcswitch.Outgoing {
×
447
                return m.isOutgoingAddBlocked.Swap(false)
×
448
        }
×
449

450
        return m.isIncomingAddBlocked.Swap(false)
×
451
}
452

UNCOV
453
func (m *mockUpdateHandler) DisableAdds(dir htlcswitch.LinkDirection) bool {
×
UNCOV
454
        if dir == htlcswitch.Outgoing {
×
UNCOV
455
                return !m.isOutgoingAddBlocked.Swap(true)
×
UNCOV
456
        }
×
457

UNCOV
458
        return !m.isIncomingAddBlocked.Swap(true)
×
459
}
460

461
func (m *mockUpdateHandler) IsFlushing(dir htlcswitch.LinkDirection) bool {
×
462
        switch dir {
×
463
        case htlcswitch.Outgoing:
×
464
                return m.isOutgoingAddBlocked.Load()
×
465
        case htlcswitch.Incoming:
×
466
                return m.isIncomingAddBlocked.Load()
×
467
        }
468

469
        return false
×
470
}
471

UNCOV
472
func (m *mockUpdateHandler) OnFlushedOnce(hook func()) {
×
UNCOV
473
        hook()
×
UNCOV
474
}
×
475
func (m *mockUpdateHandler) OnCommitOnce(
476
        _ htlcswitch.LinkDirection, hook func(),
UNCOV
477
) {
×
UNCOV
478

×
UNCOV
479
        hook()
×
UNCOV
480
}
×
481
func (m *mockUpdateHandler) InitStfu() <-chan fn.Result[lntypes.ChannelParty] {
×
482
        // TODO(proofofkeags): Implement
×
483
        c := make(chan fn.Result[lntypes.ChannelParty], 1)
×
484

×
485
        c <- fn.Errf[lntypes.ChannelParty]("InitStfu not yet implemented")
×
486

×
487
        return c
×
488
}
×
489

UNCOV
490
func newMockConn(t *testing.T, expectedMessages int) *mockMessageConn {
×
UNCOV
491
        return &mockMessageConn{
×
UNCOV
492
                t:               t,
×
UNCOV
493
                writtenMessages: make(chan []byte, expectedMessages),
×
UNCOV
494
                readMessages:    make(chan []byte, 1),
×
UNCOV
495
        }
×
UNCOV
496
}
×
497

498
// SetWriteDeadline mocks setting write deadline for our conn.
UNCOV
499
func (m *mockMessageConn) SetWriteDeadline(time.Time) error {
×
UNCOV
500
        m.writeRaceDetectingCounter++
×
UNCOV
501
        return nil
×
UNCOV
502
}
×
503

504
// Flush mocks a message conn flush.
UNCOV
505
func (m *mockMessageConn) Flush() (int, error) {
×
UNCOV
506
        m.writeRaceDetectingCounter++
×
UNCOV
507
        return 0, nil
×
UNCOV
508
}
×
509

510
// WriteMessage mocks sending of a message on our connection. It will push
511
// the bytes sent into the mock's writtenMessages channel.
UNCOV
512
func (m *mockMessageConn) WriteMessage(msg []byte) error {
×
UNCOV
513
        m.writeRaceDetectingCounter++
×
UNCOV
514

×
UNCOV
515
        msgCopy := make([]byte, len(msg))
×
UNCOV
516
        copy(msgCopy, msg)
×
UNCOV
517

×
UNCOV
518
        select {
×
UNCOV
519
        case m.writtenMessages <- msgCopy:
×
520
        case <-time.After(timeout):
×
521
                m.t.Fatalf("timeout sending message: %v", msgCopy)
×
522
        }
523

UNCOV
524
        return nil
×
525
}
526

527
// assertWrite asserts that our mock as had WriteMessage called with the byte
528
// slice we expect.
UNCOV
529
func (m *mockMessageConn) assertWrite(expected []byte) {
×
UNCOV
530
        select {
×
UNCOV
531
        case actual := <-m.writtenMessages:
×
UNCOV
532
                require.Equal(m.t, expected, actual)
×
533

534
        case <-time.After(timeout):
×
535
                m.t.Fatalf("timeout waiting for write: %v", expected)
×
536
        }
537
}
538

UNCOV
539
func (m *mockMessageConn) SetReadDeadline(t time.Time) error {
×
UNCOV
540
        m.readRaceDetectingCounter++
×
UNCOV
541
        return nil
×
UNCOV
542
}
×
543

UNCOV
544
func (m *mockMessageConn) ReadNextHeader() (uint32, error) {
×
UNCOV
545
        m.readRaceDetectingCounter++
×
UNCOV
546
        m.curReadMessage = <-m.readMessages
×
UNCOV
547
        return uint32(len(m.curReadMessage)), nil
×
UNCOV
548
}
×
549

UNCOV
550
func (m *mockMessageConn) ReadNextBody(buf []byte) ([]byte, error) {
×
UNCOV
551
        m.readRaceDetectingCounter++
×
UNCOV
552
        return m.curReadMessage, nil
×
UNCOV
553
}
×
554

UNCOV
555
func (m *mockMessageConn) RemoteAddr() net.Addr {
×
UNCOV
556
        return nil
×
UNCOV
557
}
×
558

UNCOV
559
func (m *mockMessageConn) LocalAddr() net.Addr {
×
UNCOV
560
        return nil
×
UNCOV
561
}
×
562

563
func (m *mockMessageConn) Close() error {
×
564
        return nil
×
565
}
×
566

567
// createTestPeer creates a new peer for testing and returns a context struct
568
// containing necessary handles and mock objects for conducting tests on peer
569
// functionalities.
UNCOV
570
func createTestPeer(t *testing.T) *peerTestCtx {
×
UNCOV
571
        nodeKeyLocator := keychain.KeyLocator{
×
UNCOV
572
                Family: keychain.KeyFamilyNodeKey,
×
UNCOV
573
        }
×
UNCOV
574

×
UNCOV
575
        aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(
×
UNCOV
576
                channels.AlicesPrivKey,
×
UNCOV
577
        )
×
UNCOV
578

×
UNCOV
579
        aliceKeySigner := keychain.NewPrivKeyMessageSigner(
×
UNCOV
580
                aliceKeyPriv, nodeKeyLocator,
×
UNCOV
581
        )
×
UNCOV
582

×
UNCOV
583
        aliceAddr := &net.TCPAddr{
×
UNCOV
584
                IP:   net.ParseIP("127.0.0.1"),
×
UNCOV
585
                Port: 18555,
×
UNCOV
586
        }
×
UNCOV
587
        cfgAddr := &lnwire.NetAddress{
×
UNCOV
588
                IdentityKey: aliceKeyPub,
×
UNCOV
589
                Address:     aliceAddr,
×
UNCOV
590
                ChainNet:    wire.SimNet,
×
UNCOV
591
        }
×
UNCOV
592

×
UNCOV
593
        errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize)
×
UNCOV
594
        require.NoError(t, err)
×
UNCOV
595

×
UNCOV
596
        chainIO := &mock.ChainIO{
×
UNCOV
597
                BestHeight: broadcastHeight,
×
UNCOV
598
        }
×
UNCOV
599

×
UNCOV
600
        publishTx := make(chan *wire.MsgTx)
×
UNCOV
601
        wallet := &lnwallet.LightningWallet{
×
UNCOV
602
                WalletController: &mock.WalletController{
×
UNCOV
603
                        RootKey:               aliceKeyPriv,
×
UNCOV
604
                        PublishedTransactions: publishTx,
×
UNCOV
605
                },
×
UNCOV
606
        }
×
UNCOV
607

×
UNCOV
608
        const chanActiveTimeout = time.Minute
×
UNCOV
609

×
UNCOV
610
        dbAliceGraph := graphdb.MakeTestGraph(t)
×
UNCOV
611
        require.NoError(t, dbAliceGraph.Start())
×
UNCOV
612
        t.Cleanup(func() {
×
UNCOV
613
                require.NoError(t, dbAliceGraph.Stop())
×
UNCOV
614
        })
×
615

UNCOV
616
        dbAliceChannel := channeldb.OpenForTesting(t, t.TempDir())
×
UNCOV
617

×
UNCOV
618
        nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner)
×
UNCOV
619

×
UNCOV
620
        chanStatusMgr, err := netann.NewChanStatusManager(&netann.
×
UNCOV
621
                ChanStatusConfig{
×
UNCOV
622
                ChanStatusSampleInterval: 30 * time.Second,
×
UNCOV
623
                ChanEnableTimeout:        chanActiveTimeout,
×
UNCOV
624
                ChanDisableTimeout:       2 * time.Minute,
×
UNCOV
625
                DB:                       dbAliceChannel.ChannelStateDB(),
×
UNCOV
626
                Graph:                    dbAliceGraph,
×
UNCOV
627
                MessageSigner:            nodeSignerAlice,
×
UNCOV
628
                OurPubKey:                aliceKeyPub,
×
UNCOV
629
                OurKeyLoc:                testKeyLoc,
×
UNCOV
630
                IsChannelActive: func(lnwire.ChannelID) bool {
×
631
                        return true
×
632
                },
×
633
                ApplyChannelUpdate: func(*lnwire.ChannelUpdate1,
634
                        *wire.OutPoint, bool) error {
×
635

×
636
                        return nil
×
637
                },
×
638
        })
UNCOV
639
        require.NoError(t, err)
×
UNCOV
640

×
UNCOV
641
        interceptableSwitchNotifier := &mock.ChainNotifier{
×
UNCOV
642
                EpochChan: make(chan *chainntnfs.BlockEpoch, 1),
×
UNCOV
643
        }
×
UNCOV
644
        interceptableSwitchNotifier.EpochChan <- &chainntnfs.BlockEpoch{
×
UNCOV
645
                Height: 1,
×
UNCOV
646
        }
×
UNCOV
647

×
UNCOV
648
        interceptableSwitch, err := htlcswitch.NewInterceptableSwitch(
×
UNCOV
649
                &htlcswitch.InterceptableSwitchConfig{
×
UNCOV
650
                        CltvRejectDelta:    testCltvRejectDelta,
×
UNCOV
651
                        CltvInterceptDelta: testCltvRejectDelta + 3,
×
UNCOV
652
                        Notifier:           interceptableSwitchNotifier,
×
UNCOV
653
                },
×
UNCOV
654
        )
×
UNCOV
655
        require.NoError(t, err)
×
UNCOV
656

×
UNCOV
657
        // TODO(yy): create interface for lnwallet.LightningChannel so we can
×
UNCOV
658
        // easily mock it without the following setups.
×
UNCOV
659
        notifier := &mock.ChainNotifier{
×
UNCOV
660
                SpendChan: make(chan *chainntnfs.SpendDetail),
×
UNCOV
661
                EpochChan: make(chan *chainntnfs.BlockEpoch),
×
UNCOV
662
                ConfChan:  make(chan *chainntnfs.TxConfirmation),
×
UNCOV
663
        }
×
UNCOV
664

×
UNCOV
665
        mockSwitch := &mockMessageSwitch{}
×
UNCOV
666

×
UNCOV
667
        // TODO(yy): change ChannelNotifier to be an interface.
×
UNCOV
668
        channelNotifier := channelnotifier.New(dbAliceChannel.ChannelStateDB())
×
UNCOV
669
        require.NoError(t, channelNotifier.Start())
×
UNCOV
670
        t.Cleanup(func() {
×
UNCOV
671
                require.NoError(t, channelNotifier.Stop(),
×
UNCOV
672
                        "stop channel notifier failed")
×
UNCOV
673
        })
×
674

UNCOV
675
        writeBufferPool := pool.NewWriteBuffer(
×
UNCOV
676
                pool.DefaultWriteBufferGCInterval,
×
UNCOV
677
                pool.DefaultWriteBufferExpiryInterval,
×
UNCOV
678
        )
×
UNCOV
679

×
UNCOV
680
        writePool := pool.NewWrite(
×
UNCOV
681
                writeBufferPool, 1, timeout,
×
UNCOV
682
        )
×
UNCOV
683
        require.NoError(t, writePool.Start())
×
UNCOV
684

×
UNCOV
685
        readBufferPool := pool.NewReadBuffer(
×
UNCOV
686
                pool.DefaultReadBufferGCInterval,
×
UNCOV
687
                pool.DefaultReadBufferExpiryInterval,
×
UNCOV
688
        )
×
UNCOV
689

×
UNCOV
690
        readPool := pool.NewRead(
×
UNCOV
691
                readBufferPool, 1, timeout,
×
UNCOV
692
        )
×
UNCOV
693
        require.NoError(t, readPool.Start())
×
UNCOV
694

×
UNCOV
695
        mockConn := newMockConn(t, 1)
×
UNCOV
696

×
UNCOV
697
        receivedCustomChan := make(chan *customMsg)
×
UNCOV
698

×
UNCOV
699
        var pubKey [33]byte
×
UNCOV
700
        copy(pubKey[:], aliceKeyPub.SerializeCompressed())
×
UNCOV
701

×
UNCOV
702
        estimator := chainfee.NewStaticEstimator(12500, 0)
×
UNCOV
703

×
UNCOV
704
        cfg := &Config{
×
UNCOV
705
                Addr:              cfgAddr,
×
UNCOV
706
                PubKeyBytes:       pubKey,
×
UNCOV
707
                ErrorBuffer:       errBuffer,
×
UNCOV
708
                ChainIO:           chainIO,
×
UNCOV
709
                Switch:            mockSwitch,
×
UNCOV
710
                ChanActiveTimeout: chanActiveTimeout,
×
UNCOV
711
                InterceptSwitch:   interceptableSwitch,
×
UNCOV
712
                ChannelDB:         dbAliceChannel.ChannelStateDB(),
×
UNCOV
713
                FeeEstimator:      estimator,
×
UNCOV
714
                Wallet:            wallet,
×
UNCOV
715
                ChainNotifier:     notifier,
×
UNCOV
716
                ChanStatusMgr:     chanStatusMgr,
×
UNCOV
717
                Features: lnwire.NewFeatureVector(
×
UNCOV
718
                        nil, lnwire.Features,
×
UNCOV
719
                ),
×
UNCOV
720
                DisconnectPeer: func(b *btcec.PublicKey) error {
×
721
                        return nil
×
722
                },
×
723
                ChannelNotifier:               channelNotifier,
UNCOV
724
                PrunePersistentPeerConnection: func([33]byte) {},
×
725
                LegacyFeatures:                lnwire.EmptyFeatureVector(),
726
                WritePool:                     writePool,
727
                ReadPool:                      readPool,
728
                Conn:                          mockConn,
729
                HandleCustomMessage: func(
UNCOV
730
                        peer [33]byte, msg *lnwire.Custom) error {
×
UNCOV
731

×
UNCOV
732
                        receivedCustomChan <- &customMsg{
×
UNCOV
733
                                peer: peer,
×
UNCOV
734
                                msg:  *msg,
×
UNCOV
735
                        }
×
UNCOV
736

×
UNCOV
737
                        return nil
×
UNCOV
738
                },
×
739
                PongBuf: make([]byte, lnwire.MaxPongBytes),
740
                FetchLastChanUpdate: func(chanID lnwire.ShortChannelID,
UNCOV
741
                ) (*lnwire.ChannelUpdate1, error) {
×
UNCOV
742

×
UNCOV
743
                        return &lnwire.ChannelUpdate1{}, nil
×
UNCOV
744
                },
×
745
        }
746

UNCOV
747
        alicePeer := NewBrontide(*cfg)
×
UNCOV
748

×
UNCOV
749
        return &peerTestCtx{
×
UNCOV
750
                publishTx:     publishTx,
×
UNCOV
751
                mockSwitch:    mockSwitch,
×
UNCOV
752
                peer:          alicePeer,
×
UNCOV
753
                notifier:      notifier,
×
UNCOV
754
                db:            dbAliceChannel,
×
UNCOV
755
                privKey:       aliceKeyPriv,
×
UNCOV
756
                mockConn:      mockConn,
×
UNCOV
757
                customChan:    receivedCustomChan,
×
UNCOV
758
                chanStatusMgr: chanStatusMgr,
×
UNCOV
759
        }
×
760
}
761

762
// startPeer invokes the `Start` method on the specified peer and handles any
763
// initial startup messages for testing.
764
func startPeer(t *testing.T, mockConn *mockMessageConn,
UNCOV
765
        peer *Brontide) <-chan struct{} {
×
UNCOV
766

×
UNCOV
767
        // Start the peer in a goroutine so that we can handle and test for
×
UNCOV
768
        // startup messages. Successfully sending and receiving init message,
×
UNCOV
769
        // indicates a successful startup.
×
UNCOV
770
        done := make(chan struct{})
×
UNCOV
771
        go func() {
×
UNCOV
772
                require.NoError(t, peer.Start())
×
UNCOV
773
                close(done)
×
UNCOV
774
        }()
×
775

776
        // Receive the init message that should be the first message received on
777
        // startup.
UNCOV
778
        rawMsg, err := fn.RecvOrTimeout[[]byte](
×
UNCOV
779
                mockConn.writtenMessages, timeout,
×
UNCOV
780
        )
×
UNCOV
781
        require.NoError(t, err)
×
UNCOV
782

×
UNCOV
783
        msgReader := bytes.NewReader(rawMsg)
×
UNCOV
784
        nextMsg, err := lnwire.ReadMessage(msgReader, 0)
×
UNCOV
785
        require.NoError(t, err)
×
UNCOV
786

×
UNCOV
787
        _, ok := nextMsg.(*lnwire.Init)
×
UNCOV
788
        require.True(t, ok)
×
UNCOV
789

×
UNCOV
790
        // Write the reply for the init message to complete the startup.
×
UNCOV
791
        initReplyMsg := lnwire.NewInitMessage(
×
UNCOV
792
                lnwire.NewRawFeatureVector(
×
UNCOV
793
                        lnwire.DataLossProtectRequired,
×
UNCOV
794
                        lnwire.GossipQueriesOptional,
×
UNCOV
795
                ),
×
UNCOV
796
                lnwire.NewRawFeatureVector(),
×
UNCOV
797
        )
×
UNCOV
798

×
UNCOV
799
        var b bytes.Buffer
×
UNCOV
800
        _, err = lnwire.WriteMessage(&b, initReplyMsg, 0)
×
UNCOV
801
        require.NoError(t, err)
×
UNCOV
802

×
UNCOV
803
        ok = fn.SendOrQuit[[]byte, struct{}](
×
UNCOV
804
                mockConn.readMessages, b.Bytes(), make(chan struct{}),
×
UNCOV
805
        )
×
UNCOV
806
        require.True(t, ok)
×
UNCOV
807

×
UNCOV
808
        return done
×
809
}
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