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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

0.0
/lnwallet/test_utils.go
1
package lnwallet
2

3
import (
4
        "bytes"
5
        "context"
6
        "crypto/rand"
7
        "encoding/binary"
8
        "encoding/hex"
9
        "io"
10
        prand "math/rand"
11
        "net"
12
        "testing"
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/channeldb"
19
        "github.com/lightningnetwork/lnd/fn/v2"
20
        "github.com/lightningnetwork/lnd/input"
21
        "github.com/lightningnetwork/lnd/keychain"
22
        "github.com/lightningnetwork/lnd/lntypes"
23
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
24
        "github.com/lightningnetwork/lnd/lnwire"
25
        "github.com/lightningnetwork/lnd/shachain"
26
        "github.com/lightningnetwork/lnd/tlv"
27
        "github.com/stretchr/testify/mock"
28
        "github.com/stretchr/testify/require"
29
)
30

31
var (
32
        // For simplicity a single priv key controls all of our test outputs.
33
        testWalletPrivKey = []byte{
34
                0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf,
35
                0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9,
36
                0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f,
37
                0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90,
38
        }
39

40
        // We're alice :)
41
        bobsPrivKey = []byte{
42
                0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
43
                0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
44
                0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
45
                0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
46
        }
47

48
        // Use a hard-coded HD seed.
49
        testHdSeed = chainhash.Hash{
50
                0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
51
                0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
52
                0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
53
                0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
54
        }
55

56
        // A serializable txn for testing funding txn.
57
        testTx = &wire.MsgTx{
58
                Version: 1,
59
                TxIn: []*wire.TxIn{
60
                        {
61
                                PreviousOutPoint: wire.OutPoint{
62
                                        Hash:  chainhash.Hash{},
63
                                        Index: 0xffffffff,
64
                                },
65
                                SignatureScript: []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62},
66
                                Sequence:        0xffffffff,
67
                        },
68
                },
69
                TxOut: []*wire.TxOut{
70
                        {
71
                                Value: 5000000000,
72
                                PkScript: []byte{
73
                                        0x41, // OP_DATA_65
74
                                        0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
75
                                        0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
76
                                        0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
77
                                        0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
78
                                        0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
79
                                        0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
80
                                        0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
81
                                        0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
82
                                        0xa6, // 65-byte signature
83
                                        0xac, // OP_CHECKSIG
84
                                },
85
                        },
86
                },
87
                LockTime: 5,
88
        }
89

90
        // A valid, DER-encoded signature (taken from btcec unit tests).
91
        testSigBytes = []byte{
92
                0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
93
                0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3,
94
                0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32,
95
                0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab,
96
                0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15,
97
                0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
98
                0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c,
99
                0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22,
100
                0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
101
        }
102

103
        aliceDustLimit = btcutil.Amount(200)
104
        bobDustLimit   = btcutil.Amount(1300)
105

106
        testChannelCapacity float64 = 10
107

108
        // ctxb is a context that will never be cancelled, that is used in
109
        // place of a real quit context.
110
        ctxb = context.Background()
111
)
112

113
// CreateTestChannels creates to fully populated channels to be used within
114
// testing fixtures. The channels will be returned as if the funding process
115
// has just completed.  The channel itself is funded with 10 BTC, with 5 BTC
116
// allocated to each side. Within the channel, Alice is the initiator. If
117
// tweaklessCommits is true, then the commits within the channels will use the
118
// new format, otherwise the legacy format.
119
func CreateTestChannels(t *testing.T, chanType channeldb.ChannelType,
120
        dbModifiers ...channeldb.OptionModifier) (*LightningChannel,
UNCOV
121
        *LightningChannel, error) {
×
UNCOV
122

×
UNCOV
123
        channelCapacity, err := btcutil.NewAmount(testChannelCapacity)
×
UNCOV
124
        if err != nil {
×
125
                return nil, nil, err
×
126
        }
×
127

UNCOV
128
        channelBal := channelCapacity / 2
×
UNCOV
129
        csvTimeoutAlice := uint32(5)
×
UNCOV
130
        csvTimeoutBob := uint32(4)
×
UNCOV
131
        isAliceInitiator := true
×
UNCOV
132

×
UNCOV
133
        prevOut := &wire.OutPoint{
×
UNCOV
134
                Hash:  chainhash.Hash(testHdSeed),
×
UNCOV
135
                Index: prand.Uint32(),
×
UNCOV
136
        }
×
UNCOV
137
        fundingTxIn := wire.NewTxIn(prevOut, nil, nil)
×
UNCOV
138

×
UNCOV
139
        // For each party, we'll create a distinct set of keys in order to
×
UNCOV
140
        // emulate the typical set up with live channels.
×
UNCOV
141
        var (
×
UNCOV
142
                aliceKeys []*btcec.PrivateKey
×
UNCOV
143
                bobKeys   []*btcec.PrivateKey
×
UNCOV
144
        )
×
UNCOV
145
        for i := 0; i < 5; i++ {
×
UNCOV
146
                key := make([]byte, len(testWalletPrivKey))
×
UNCOV
147
                copy(key[:], testWalletPrivKey[:])
×
UNCOV
148
                key[0] ^= byte(i + 1)
×
UNCOV
149

×
UNCOV
150
                aliceKey, _ := btcec.PrivKeyFromBytes(key)
×
UNCOV
151
                aliceKeys = append(aliceKeys, aliceKey)
×
UNCOV
152

×
UNCOV
153
                key = make([]byte, len(bobsPrivKey))
×
UNCOV
154
                copy(key[:], bobsPrivKey)
×
UNCOV
155
                key[0] ^= byte(i + 1)
×
UNCOV
156

×
UNCOV
157
                bobKey, _ := btcec.PrivKeyFromBytes(key)
×
UNCOV
158
                bobKeys = append(bobKeys, bobKey)
×
UNCOV
159
        }
×
160

UNCOV
161
        aliceCfg := channeldb.ChannelConfig{
×
UNCOV
162
                ChannelStateBounds: channeldb.ChannelStateBounds{
×
UNCOV
163
                        MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
×
UNCOV
164
                        ChanReserve:      channelCapacity / 100,
×
UNCOV
165
                        MinHTLC:          0,
×
UNCOV
166
                        MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
×
UNCOV
167
                },
×
UNCOV
168
                CommitmentParams: channeldb.CommitmentParams{
×
UNCOV
169
                        DustLimit: aliceDustLimit,
×
UNCOV
170
                        CsvDelay:  uint16(csvTimeoutAlice),
×
UNCOV
171
                },
×
UNCOV
172
                MultiSigKey: keychain.KeyDescriptor{
×
UNCOV
173
                        PubKey: aliceKeys[0].PubKey(),
×
UNCOV
174
                },
×
UNCOV
175
                RevocationBasePoint: keychain.KeyDescriptor{
×
UNCOV
176
                        PubKey: aliceKeys[1].PubKey(),
×
UNCOV
177
                },
×
UNCOV
178
                PaymentBasePoint: keychain.KeyDescriptor{
×
UNCOV
179
                        PubKey: aliceKeys[2].PubKey(),
×
UNCOV
180
                },
×
UNCOV
181
                DelayBasePoint: keychain.KeyDescriptor{
×
UNCOV
182
                        PubKey: aliceKeys[3].PubKey(),
×
UNCOV
183
                },
×
UNCOV
184
                HtlcBasePoint: keychain.KeyDescriptor{
×
UNCOV
185
                        PubKey: aliceKeys[4].PubKey(),
×
UNCOV
186
                },
×
UNCOV
187
        }
×
UNCOV
188
        bobCfg := channeldb.ChannelConfig{
×
UNCOV
189
                ChannelStateBounds: channeldb.ChannelStateBounds{
×
UNCOV
190
                        MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
×
UNCOV
191
                        ChanReserve:      channelCapacity / 100,
×
UNCOV
192
                        MinHTLC:          0,
×
UNCOV
193
                        MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
×
UNCOV
194
                },
×
UNCOV
195
                CommitmentParams: channeldb.CommitmentParams{
×
UNCOV
196
                        DustLimit: bobDustLimit,
×
UNCOV
197
                        CsvDelay:  uint16(csvTimeoutBob),
×
UNCOV
198
                },
×
UNCOV
199
                MultiSigKey: keychain.KeyDescriptor{
×
UNCOV
200
                        PubKey: bobKeys[0].PubKey(),
×
UNCOV
201
                },
×
UNCOV
202
                RevocationBasePoint: keychain.KeyDescriptor{
×
UNCOV
203
                        PubKey: bobKeys[1].PubKey(),
×
UNCOV
204
                },
×
UNCOV
205
                PaymentBasePoint: keychain.KeyDescriptor{
×
UNCOV
206
                        PubKey: bobKeys[2].PubKey(),
×
UNCOV
207
                },
×
UNCOV
208
                DelayBasePoint: keychain.KeyDescriptor{
×
UNCOV
209
                        PubKey: bobKeys[3].PubKey(),
×
UNCOV
210
                },
×
UNCOV
211
                HtlcBasePoint: keychain.KeyDescriptor{
×
UNCOV
212
                        PubKey: bobKeys[4].PubKey(),
×
UNCOV
213
                },
×
UNCOV
214
        }
×
UNCOV
215

×
UNCOV
216
        bobRoot, err := chainhash.NewHash(bobKeys[0].Serialize())
×
UNCOV
217
        if err != nil {
×
218
                return nil, nil, err
×
219
        }
×
UNCOV
220
        bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot)
×
UNCOV
221
        bobFirstRevoke, err := bobPreimageProducer.AtIndex(0)
×
UNCOV
222
        if err != nil {
×
223
                return nil, nil, err
×
224
        }
×
UNCOV
225
        bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
×
UNCOV
226

×
UNCOV
227
        aliceRoot, err := chainhash.NewHash(aliceKeys[0].Serialize())
×
UNCOV
228
        if err != nil {
×
229
                return nil, nil, err
×
230
        }
×
UNCOV
231
        alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot)
×
UNCOV
232
        aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0)
×
UNCOV
233
        if err != nil {
×
234
                return nil, nil, err
×
235
        }
×
UNCOV
236
        aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
×
UNCOV
237

×
UNCOV
238
        aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns(
×
UNCOV
239
                channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
×
UNCOV
240
                bobCommitPoint, *fundingTxIn, chanType, isAliceInitiator, 0,
×
UNCOV
241
        )
×
UNCOV
242
        if err != nil {
×
243
                return nil, nil, err
×
244
        }
×
245

UNCOV
246
        dbAlice := channeldb.OpenForTesting(t, t.TempDir(), dbModifiers...)
×
UNCOV
247
        dbBob := channeldb.OpenForTesting(t, t.TempDir(), dbModifiers...)
×
UNCOV
248

×
UNCOV
249
        estimator := chainfee.NewStaticEstimator(6000, 0)
×
UNCOV
250
        feePerKw, err := estimator.EstimateFeePerKW(1)
×
UNCOV
251
        if err != nil {
×
252
                return nil, nil, err
×
253
        }
×
UNCOV
254
        commitFee := calcStaticFee(chanType, 0)
×
UNCOV
255
        var anchorAmt btcutil.Amount
×
UNCOV
256
        if chanType.HasAnchors() {
×
UNCOV
257
                anchorAmt += 2 * AnchorSize
×
UNCOV
258
        }
×
259

UNCOV
260
        aliceBalance := lnwire.NewMSatFromSatoshis(
×
UNCOV
261
                channelBal - commitFee - anchorAmt,
×
UNCOV
262
        )
×
UNCOV
263
        bobBalance := lnwire.NewMSatFromSatoshis(channelBal)
×
UNCOV
264

×
UNCOV
265
        aliceLocalCommit := channeldb.ChannelCommitment{
×
UNCOV
266
                CommitHeight:  0,
×
UNCOV
267
                LocalBalance:  aliceBalance,
×
UNCOV
268
                RemoteBalance: bobBalance,
×
UNCOV
269
                CommitFee:     commitFee,
×
UNCOV
270
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
271
                CommitTx:      aliceCommitTx,
×
UNCOV
272
                CommitSig:     testSigBytes,
×
UNCOV
273
        }
×
UNCOV
274
        aliceRemoteCommit := channeldb.ChannelCommitment{
×
UNCOV
275
                CommitHeight:  0,
×
UNCOV
276
                LocalBalance:  aliceBalance,
×
UNCOV
277
                RemoteBalance: bobBalance,
×
UNCOV
278
                CommitFee:     commitFee,
×
UNCOV
279
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
280
                CommitTx:      bobCommitTx,
×
UNCOV
281
                CommitSig:     testSigBytes,
×
UNCOV
282
        }
×
UNCOV
283
        bobLocalCommit := channeldb.ChannelCommitment{
×
UNCOV
284
                CommitHeight:  0,
×
UNCOV
285
                LocalBalance:  bobBalance,
×
UNCOV
286
                RemoteBalance: aliceBalance,
×
UNCOV
287
                CommitFee:     commitFee,
×
UNCOV
288
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
289
                CommitTx:      bobCommitTx,
×
UNCOV
290
                CommitSig:     testSigBytes,
×
UNCOV
291
        }
×
UNCOV
292
        bobRemoteCommit := channeldb.ChannelCommitment{
×
UNCOV
293
                CommitHeight:  0,
×
UNCOV
294
                LocalBalance:  bobBalance,
×
UNCOV
295
                RemoteBalance: aliceBalance,
×
UNCOV
296
                CommitFee:     commitFee,
×
UNCOV
297
                FeePerKw:      btcutil.Amount(feePerKw),
×
UNCOV
298
                CommitTx:      aliceCommitTx,
×
UNCOV
299
                CommitSig:     testSigBytes,
×
UNCOV
300
        }
×
UNCOV
301

×
UNCOV
302
        var chanIDBytes [8]byte
×
UNCOV
303
        if _, err := io.ReadFull(rand.Reader, chanIDBytes[:]); err != nil {
×
304
                return nil, nil, err
×
305
        }
×
306

UNCOV
307
        shortChanID := lnwire.NewShortChanIDFromInt(
×
UNCOV
308
                binary.BigEndian.Uint64(chanIDBytes[:]),
×
UNCOV
309
        )
×
UNCOV
310

×
UNCOV
311
        aliceChannelState := &channeldb.OpenChannel{
×
UNCOV
312
                LocalChanCfg:            aliceCfg,
×
UNCOV
313
                RemoteChanCfg:           bobCfg,
×
UNCOV
314
                IdentityPub:             aliceKeys[0].PubKey(),
×
UNCOV
315
                FundingOutpoint:         *prevOut,
×
UNCOV
316
                ShortChannelID:          shortChanID,
×
UNCOV
317
                ChanType:                chanType,
×
UNCOV
318
                IsInitiator:             isAliceInitiator,
×
UNCOV
319
                Capacity:                channelCapacity,
×
UNCOV
320
                RemoteCurrentRevocation: bobCommitPoint,
×
UNCOV
321
                RevocationProducer:      alicePreimageProducer,
×
UNCOV
322
                RevocationStore:         shachain.NewRevocationStore(),
×
UNCOV
323
                LocalCommitment:         aliceLocalCommit,
×
UNCOV
324
                RemoteCommitment:        aliceRemoteCommit,
×
UNCOV
325
                Db:                      dbAlice.ChannelStateDB(),
×
UNCOV
326
                Packager:                channeldb.NewChannelPackager(shortChanID),
×
UNCOV
327
                FundingTxn:              testTx,
×
UNCOV
328
        }
×
UNCOV
329
        bobChannelState := &channeldb.OpenChannel{
×
UNCOV
330
                LocalChanCfg:            bobCfg,
×
UNCOV
331
                RemoteChanCfg:           aliceCfg,
×
UNCOV
332
                IdentityPub:             bobKeys[0].PubKey(),
×
UNCOV
333
                FundingOutpoint:         *prevOut,
×
UNCOV
334
                ShortChannelID:          shortChanID,
×
UNCOV
335
                ChanType:                chanType,
×
UNCOV
336
                IsInitiator:             !isAliceInitiator,
×
UNCOV
337
                Capacity:                channelCapacity,
×
UNCOV
338
                RemoteCurrentRevocation: aliceCommitPoint,
×
UNCOV
339
                RevocationProducer:      bobPreimageProducer,
×
UNCOV
340
                RevocationStore:         shachain.NewRevocationStore(),
×
UNCOV
341
                LocalCommitment:         bobLocalCommit,
×
UNCOV
342
                RemoteCommitment:        bobRemoteCommit,
×
UNCOV
343
                Db:                      dbBob.ChannelStateDB(),
×
UNCOV
344
                Packager:                channeldb.NewChannelPackager(shortChanID),
×
UNCOV
345
        }
×
UNCOV
346

×
UNCOV
347
        // If the channel type has a tapscript root, then we'll also specify
×
UNCOV
348
        // one here to apply to both the channels.
×
UNCOV
349
        if chanType.HasTapscriptRoot() {
×
UNCOV
350
                var tapscriptRoot chainhash.Hash
×
UNCOV
351
                _, err := io.ReadFull(rand.Reader, tapscriptRoot[:])
×
UNCOV
352
                if err != nil {
×
353
                        return nil, nil, err
×
354
                }
×
355

UNCOV
356
                someRoot := fn.Some(tapscriptRoot)
×
UNCOV
357

×
UNCOV
358
                aliceChannelState.TapscriptRoot = someRoot
×
UNCOV
359
                bobChannelState.TapscriptRoot = someRoot
×
360
        }
361

UNCOV
362
        aliceSigner := input.NewMockSigner(aliceKeys, nil)
×
UNCOV
363
        bobSigner := input.NewMockSigner(bobKeys, nil)
×
UNCOV
364

×
UNCOV
365
        // TODO(roasbeef): make mock version of pre-image store
×
UNCOV
366

×
UNCOV
367
        auxSigner := NewDefaultAuxSignerMock(t)
×
UNCOV
368

×
UNCOV
369
        alicePool := NewSigPool(1, aliceSigner)
×
UNCOV
370
        channelAlice, err := NewLightningChannel(
×
UNCOV
371
                aliceSigner, aliceChannelState, alicePool,
×
UNCOV
372
                WithLeafStore(&MockAuxLeafStore{}),
×
UNCOV
373
                WithAuxSigner(auxSigner),
×
UNCOV
374
        )
×
UNCOV
375
        if err != nil {
×
376
                return nil, nil, err
×
377
        }
×
UNCOV
378
        alicePool.Start()
×
UNCOV
379
        t.Cleanup(func() {
×
UNCOV
380
                require.NoError(t, alicePool.Stop())
×
UNCOV
381
        })
×
382

UNCOV
383
        obfuscator := createStateHintObfuscator(aliceChannelState)
×
UNCOV
384

×
UNCOV
385
        bobPool := NewSigPool(1, bobSigner)
×
UNCOV
386
        channelBob, err := NewLightningChannel(
×
UNCOV
387
                bobSigner, bobChannelState, bobPool,
×
UNCOV
388
                WithLeafStore(&MockAuxLeafStore{}),
×
UNCOV
389
                WithAuxSigner(auxSigner),
×
UNCOV
390
        )
×
UNCOV
391
        if err != nil {
×
392
                return nil, nil, err
×
393
        }
×
UNCOV
394
        bobPool.Start()
×
UNCOV
395
        t.Cleanup(func() {
×
UNCOV
396
                require.NoError(t, bobPool.Stop())
×
UNCOV
397
        })
×
398

UNCOV
399
        err = SetStateNumHint(
×
UNCOV
400
                aliceCommitTx, 0, obfuscator,
×
UNCOV
401
        )
×
UNCOV
402
        if err != nil {
×
403
                return nil, nil, err
×
404
        }
×
UNCOV
405
        err = SetStateNumHint(
×
UNCOV
406
                bobCommitTx, 0, obfuscator,
×
UNCOV
407
        )
×
UNCOV
408
        if err != nil {
×
409
                return nil, nil, err
×
410
        }
×
411

UNCOV
412
        addr := &net.TCPAddr{
×
UNCOV
413
                IP:   net.ParseIP("127.0.0.1"),
×
UNCOV
414
                Port: 18556,
×
UNCOV
415
        }
×
UNCOV
416
        if err := channelAlice.channelState.SyncPending(addr, 101); err != nil {
×
417
                return nil, nil, err
×
418
        }
×
419

UNCOV
420
        addr = &net.TCPAddr{
×
UNCOV
421
                IP:   net.ParseIP("127.0.0.1"),
×
UNCOV
422
                Port: 18555,
×
UNCOV
423
        }
×
UNCOV
424

×
UNCOV
425
        if err := channelBob.channelState.SyncPending(addr, 101); err != nil {
×
426
                return nil, nil, err
×
427
        }
×
428

429
        // Now that the channel are open, simulate the start of a session by
430
        // having Alice and Bob extend their revocation windows to each other.
UNCOV
431
        err = initRevocationWindows(channelAlice, channelBob)
×
UNCOV
432
        if err != nil {
×
433
                return nil, nil, err
×
434
        }
×
435

UNCOV
436
        return channelAlice, channelBob, nil
×
437
}
438

439
// initMusigNonce is used to manually setup musig2 nonces for a new channel,
440
// outside the normal chan-reest flow.
UNCOV
441
func initMusigNonce(chanA, chanB *LightningChannel) error {
×
UNCOV
442
        chanANonces, err := chanA.GenMusigNonces()
×
UNCOV
443
        if err != nil {
×
444
                return err
×
445
        }
×
UNCOV
446
        chanBNonces, err := chanB.GenMusigNonces()
×
UNCOV
447
        if err != nil {
×
448
                return err
×
449
        }
×
450

UNCOV
451
        if err := chanA.InitRemoteMusigNonces(chanBNonces); err != nil {
×
452
                return err
×
453
        }
×
UNCOV
454
        if err := chanB.InitRemoteMusigNonces(chanANonces); err != nil {
×
455
                return err
×
456
        }
×
457

UNCOV
458
        return nil
×
459
}
460

461
// initRevocationWindows simulates a new channel being opened within the p2p
462
// network by populating the initial revocation windows of the passed
463
// commitment state machines.
UNCOV
464
func initRevocationWindows(chanA, chanB *LightningChannel) error {
×
UNCOV
465
        // If these are taproot chanenls, then we need to also simulate sending
×
UNCOV
466
        // either FundingLocked or ChannelReestablish by calling
×
UNCOV
467
        // InitRemoteMusigNonces for both sides.
×
UNCOV
468
        if chanA.channelState.ChanType.IsTaproot() {
×
UNCOV
469
                if err := initMusigNonce(chanA, chanB); err != nil {
×
470
                        return err
×
471
                }
×
472
        }
473

UNCOV
474
        aliceNextRevoke, err := chanA.NextRevocationKey()
×
UNCOV
475
        if err != nil {
×
476
                return err
×
477
        }
×
UNCOV
478
        if err := chanB.InitNextRevocation(aliceNextRevoke); err != nil {
×
479
                return err
×
480
        }
×
481

UNCOV
482
        bobNextRevoke, err := chanB.NextRevocationKey()
×
UNCOV
483
        if err != nil {
×
484
                return err
×
485
        }
×
UNCOV
486
        if err := chanA.InitNextRevocation(bobNextRevoke); err != nil {
×
487
                return err
×
488
        }
×
489

UNCOV
490
        return nil
×
491
}
492

493
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
UNCOV
494
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
×
UNCOV
495
        bytes, err := hex.DecodeString(keyHex)
×
UNCOV
496
        if err != nil {
×
497
                return nil, err
×
498
        }
×
UNCOV
499
        return btcec.ParsePubKey(bytes)
×
500
}
501

502
// privkeyFromHex parses a Bitcoin private key from a hex encoded string.
UNCOV
503
func privkeyFromHex(keyHex string) (*btcec.PrivateKey, error) {
×
UNCOV
504
        bytes, err := hex.DecodeString(keyHex)
×
UNCOV
505
        if err != nil {
×
506
                return nil, err
×
507
        }
×
UNCOV
508
        key, _ := btcec.PrivKeyFromBytes(bytes)
×
UNCOV
509
        return key, nil
×
510

511
}
512

513
// blockFromHex parses a full Bitcoin block from a hex encoded string.
514
func blockFromHex(blockHex string) (*btcutil.Block, error) {
×
515
        bytes, err := hex.DecodeString(blockHex)
×
516
        if err != nil {
×
517
                return nil, err
×
518
        }
×
519
        return btcutil.NewBlockFromBytes(bytes)
×
520
}
521

522
// txFromHex parses a full Bitcoin transaction from a hex encoded string.
UNCOV
523
func txFromHex(txHex string) (*btcutil.Tx, error) {
×
UNCOV
524
        bytes, err := hex.DecodeString(txHex)
×
UNCOV
525
        if err != nil {
×
526
                return nil, err
×
527
        }
×
UNCOV
528
        return btcutil.NewTxFromBytes(bytes)
×
529
}
530

531
// calcStaticFee calculates appropriate fees for commitment transactions.  This
532
// function provides a simple way to allow test balance assertions to take fee
533
// calculations into account.
534
//
535
// TODO(bvu): Refactor when dynamic fee estimation is added.
UNCOV
536
func calcStaticFee(chanType channeldb.ChannelType, numHTLCs int) btcutil.Amount {
×
UNCOV
537
        const (
×
UNCOV
538
                htlcWeight = 172
×
UNCOV
539
                feePerKw   = btcutil.Amount(24/4) * 1000
×
UNCOV
540
        )
×
UNCOV
541
        htlcsWeight := htlcWeight * int64(numHTLCs)
×
UNCOV
542
        totalWeight := CommitWeight(chanType) + lntypes.WeightUnit(htlcsWeight)
×
UNCOV
543

×
UNCOV
544
        return feePerKw * (btcutil.Amount(totalWeight)) / 1000
×
UNCOV
545
}
×
546

547
// ForceStateTransition executes the necessary interaction between the two
548
// commitment state machines to transition to a new state locking in any
549
// pending updates. This method is useful when testing interactions between two
550
// live state machines.
UNCOV
551
func ForceStateTransition(chanA, chanB *LightningChannel) error {
×
UNCOV
552
        aliceNewCommit, err := chanA.SignNextCommitment(ctxb)
×
UNCOV
553
        if err != nil {
×
554
                return err
×
555
        }
×
UNCOV
556
        err = chanB.ReceiveNewCommitment(aliceNewCommit.CommitSigs)
×
UNCOV
557
        if err != nil {
×
558
                return err
×
559
        }
×
560

UNCOV
561
        bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
×
UNCOV
562
        if err != nil {
×
563
                return err
×
564
        }
×
UNCOV
565
        bobNewCommit, err := chanB.SignNextCommitment(ctxb)
×
UNCOV
566
        if err != nil {
×
567
                return err
×
568
        }
×
569

UNCOV
570
        _, _, err = chanA.ReceiveRevocation(bobRevocation)
×
UNCOV
571
        if err != nil {
×
572
                return err
×
573
        }
×
UNCOV
574
        err = chanA.ReceiveNewCommitment(bobNewCommit.CommitSigs)
×
UNCOV
575
        if err != nil {
×
576
                return err
×
577
        }
×
578

UNCOV
579
        aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
×
UNCOV
580
        if err != nil {
×
581
                return err
×
582
        }
×
UNCOV
583
        _, _, err = chanB.ReceiveRevocation(aliceRevocation)
×
UNCOV
584
        if err != nil {
×
585
                return err
×
586
        }
×
587

UNCOV
588
        return nil
×
589
}
590

UNCOV
591
func NewDefaultAuxSignerMock(t *testing.T) *MockAuxSigner {
×
UNCOV
592
        auxSigner := NewAuxSignerMock(EmptyMockJobHandler)
×
UNCOV
593

×
UNCOV
594
        type testSigBlob struct {
×
UNCOV
595
                BlobInt tlv.RecordT[tlv.TlvType65634, uint16]
×
UNCOV
596
        }
×
UNCOV
597

×
UNCOV
598
        var sigBlobBuf bytes.Buffer
×
UNCOV
599
        sigBlob := testSigBlob{
×
UNCOV
600
                BlobInt: tlv.NewPrimitiveRecord[tlv.TlvType65634, uint16](5),
×
UNCOV
601
        }
×
UNCOV
602
        tlvStream, err := tlv.NewStream(sigBlob.BlobInt.Record())
×
UNCOV
603
        require.NoError(t, err, "unable to create tlv stream")
×
UNCOV
604
        require.NoError(t, tlvStream.Encode(&sigBlobBuf))
×
UNCOV
605

×
UNCOV
606
        auxSigner.On(
×
UNCOV
607
                "SubmitSecondLevelSigBatch", mock.Anything, mock.Anything,
×
UNCOV
608
                mock.Anything,
×
UNCOV
609
        ).Return(nil)
×
UNCOV
610
        auxSigner.On(
×
UNCOV
611
                "PackSigs", mock.Anything,
×
UNCOV
612
        ).Return(fn.Ok(fn.Some(sigBlobBuf.Bytes())))
×
UNCOV
613
        auxSigner.On(
×
UNCOV
614
                "UnpackSigs", mock.Anything,
×
UNCOV
615
        ).Return(fn.Ok([]fn.Option[tlv.Blob]{
×
UNCOV
616
                fn.Some(sigBlobBuf.Bytes()),
×
UNCOV
617
        }))
×
UNCOV
618
        auxSigner.On(
×
UNCOV
619
                "VerifySecondLevelSigs", mock.Anything, mock.Anything,
×
UNCOV
620
                mock.Anything,
×
UNCOV
621
        ).Return(nil)
×
UNCOV
622

×
UNCOV
623
        return auxSigner
×
UNCOV
624
}
×
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