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

lightningnetwork / lnd / 11292787765

11 Oct 2024 12:58PM UTC coverage: 49.179% (-9.5%) from 58.716%
11292787765

push

github

web-flow
Merge pull request #9168 from feelancer21/fix-lncli-wallet-proto

lnrpc: fix lncli documentation tags in walletkit.proto

97369 of 197987 relevant lines covered (49.18%)

1.04 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
        "crypto/rand"
6
        "encoding/binary"
7
        "encoding/hex"
8
        "io"
9
        prand "math/rand"
10
        "net"
11
        "testing"
12

13
        "github.com/btcsuite/btcd/btcec/v2"
14
        "github.com/btcsuite/btcd/btcutil"
15
        "github.com/btcsuite/btcd/chaincfg/chainhash"
16
        "github.com/btcsuite/btcd/wire"
17
        "github.com/lightningnetwork/lnd/channeldb"
18
        "github.com/lightningnetwork/lnd/fn"
19
        "github.com/lightningnetwork/lnd/input"
20
        "github.com/lightningnetwork/lnd/keychain"
21
        "github.com/lightningnetwork/lnd/lntypes"
22
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
23
        "github.com/lightningnetwork/lnd/lnwire"
24
        "github.com/lightningnetwork/lnd/shachain"
25
        "github.com/lightningnetwork/lnd/tlv"
26
        "github.com/stretchr/testify/mock"
27
        "github.com/stretchr/testify/require"
28
)
29

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

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

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

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

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

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

105
        testChannelCapacity float64 = 10
106
)
107

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

×
118
        channelCapacity, err := btcutil.NewAmount(testChannelCapacity)
×
119
        if err != nil {
×
120
                return nil, nil, err
×
121
        }
×
122

123
        channelBal := channelCapacity / 2
×
124
        csvTimeoutAlice := uint32(5)
×
125
        csvTimeoutBob := uint32(4)
×
126
        isAliceInitiator := true
×
127

×
128
        prevOut := &wire.OutPoint{
×
129
                Hash:  chainhash.Hash(testHdSeed),
×
130
                Index: prand.Uint32(),
×
131
        }
×
132
        fundingTxIn := wire.NewTxIn(prevOut, nil, nil)
×
133

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

×
145
                aliceKey, _ := btcec.PrivKeyFromBytes(key)
×
146
                aliceKeys = append(aliceKeys, aliceKey)
×
147

×
148
                key = make([]byte, len(bobsPrivKey))
×
149
                copy(key[:], bobsPrivKey)
×
150
                key[0] ^= byte(i + 1)
×
151

×
152
                bobKey, _ := btcec.PrivKeyFromBytes(key)
×
153
                bobKeys = append(bobKeys, bobKey)
×
154
        }
×
155

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

×
211
        bobRoot, err := chainhash.NewHash(bobKeys[0].Serialize())
×
212
        if err != nil {
×
213
                return nil, nil, err
×
214
        }
×
215
        bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot)
×
216
        bobFirstRevoke, err := bobPreimageProducer.AtIndex(0)
×
217
        if err != nil {
×
218
                return nil, nil, err
×
219
        }
×
220
        bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
×
221

×
222
        aliceRoot, err := chainhash.NewHash(aliceKeys[0].Serialize())
×
223
        if err != nil {
×
224
                return nil, nil, err
×
225
        }
×
226
        alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot)
×
227
        aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0)
×
228
        if err != nil {
×
229
                return nil, nil, err
×
230
        }
×
231
        aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
×
232

×
233
        aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns(
×
234
                channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
×
235
                bobCommitPoint, *fundingTxIn, chanType, isAliceInitiator, 0,
×
236
        )
×
237
        if err != nil {
×
238
                return nil, nil, err
×
239
        }
×
240

241
        dbAlice, err := channeldb.Open(t.TempDir(), dbModifiers...)
×
242
        if err != nil {
×
243
                return nil, nil, err
×
244
        }
×
245
        t.Cleanup(func() {
×
246
                require.NoError(t, dbAlice.Close())
×
247
        })
×
248

249
        dbBob, err := channeldb.Open(t.TempDir(), dbModifiers...)
×
250
        if err != nil {
×
251
                return nil, nil, err
×
252
        }
×
253
        t.Cleanup(func() {
×
254
                require.NoError(t, dbBob.Close())
×
255
        })
×
256

257
        estimator := chainfee.NewStaticEstimator(6000, 0)
×
258
        feePerKw, err := estimator.EstimateFeePerKW(1)
×
259
        if err != nil {
×
260
                return nil, nil, err
×
261
        }
×
262
        commitFee := calcStaticFee(chanType, 0)
×
263
        var anchorAmt btcutil.Amount
×
264
        if chanType.HasAnchors() {
×
265
                anchorAmt += 2 * AnchorSize
×
266
        }
×
267

268
        aliceBalance := lnwire.NewMSatFromSatoshis(
×
269
                channelBal - commitFee - anchorAmt,
×
270
        )
×
271
        bobBalance := lnwire.NewMSatFromSatoshis(channelBal)
×
272

×
273
        aliceLocalCommit := channeldb.ChannelCommitment{
×
274
                CommitHeight:  0,
×
275
                LocalBalance:  aliceBalance,
×
276
                RemoteBalance: bobBalance,
×
277
                CommitFee:     commitFee,
×
278
                FeePerKw:      btcutil.Amount(feePerKw),
×
279
                CommitTx:      aliceCommitTx,
×
280
                CommitSig:     testSigBytes,
×
281
        }
×
282
        aliceRemoteCommit := channeldb.ChannelCommitment{
×
283
                CommitHeight:  0,
×
284
                LocalBalance:  aliceBalance,
×
285
                RemoteBalance: bobBalance,
×
286
                CommitFee:     commitFee,
×
287
                FeePerKw:      btcutil.Amount(feePerKw),
×
288
                CommitTx:      bobCommitTx,
×
289
                CommitSig:     testSigBytes,
×
290
        }
×
291
        bobLocalCommit := channeldb.ChannelCommitment{
×
292
                CommitHeight:  0,
×
293
                LocalBalance:  bobBalance,
×
294
                RemoteBalance: aliceBalance,
×
295
                CommitFee:     commitFee,
×
296
                FeePerKw:      btcutil.Amount(feePerKw),
×
297
                CommitTx:      bobCommitTx,
×
298
                CommitSig:     testSigBytes,
×
299
        }
×
300
        bobRemoteCommit := channeldb.ChannelCommitment{
×
301
                CommitHeight:  0,
×
302
                LocalBalance:  bobBalance,
×
303
                RemoteBalance: aliceBalance,
×
304
                CommitFee:     commitFee,
×
305
                FeePerKw:      btcutil.Amount(feePerKw),
×
306
                CommitTx:      aliceCommitTx,
×
307
                CommitSig:     testSigBytes,
×
308
        }
×
309

×
310
        var chanIDBytes [8]byte
×
311
        if _, err := io.ReadFull(rand.Reader, chanIDBytes[:]); err != nil {
×
312
                return nil, nil, err
×
313
        }
×
314

315
        shortChanID := lnwire.NewShortChanIDFromInt(
×
316
                binary.BigEndian.Uint64(chanIDBytes[:]),
×
317
        )
×
318

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

×
355
        // If the channel type has a tapscript root, then we'll also specify
×
356
        // one here to apply to both the channels.
×
357
        if chanType.HasTapscriptRoot() {
×
358
                var tapscriptRoot chainhash.Hash
×
359
                _, err := io.ReadFull(rand.Reader, tapscriptRoot[:])
×
360
                if err != nil {
×
361
                        return nil, nil, err
×
362
                }
×
363

364
                someRoot := fn.Some(tapscriptRoot)
×
365

×
366
                aliceChannelState.TapscriptRoot = someRoot
×
367
                bobChannelState.TapscriptRoot = someRoot
×
368
        }
369

370
        aliceSigner := input.NewMockSigner(aliceKeys, nil)
×
371
        bobSigner := input.NewMockSigner(bobKeys, nil)
×
372

×
373
        // TODO(roasbeef): make mock version of pre-image store
×
374

×
375
        auxSigner := NewDefaultAuxSignerMock(t)
×
376

×
377
        alicePool := NewSigPool(1, aliceSigner)
×
378
        channelAlice, err := NewLightningChannel(
×
379
                aliceSigner, aliceChannelState, alicePool,
×
380
                WithLeafStore(&MockAuxLeafStore{}),
×
381
                WithAuxSigner(auxSigner),
×
382
        )
×
383
        if err != nil {
×
384
                return nil, nil, err
×
385
        }
×
386
        alicePool.Start()
×
387
        t.Cleanup(func() {
×
388
                require.NoError(t, alicePool.Stop())
×
389
        })
×
390

391
        obfuscator := createStateHintObfuscator(aliceChannelState)
×
392

×
393
        bobPool := NewSigPool(1, bobSigner)
×
394
        channelBob, err := NewLightningChannel(
×
395
                bobSigner, bobChannelState, bobPool,
×
396
                WithLeafStore(&MockAuxLeafStore{}),
×
397
                WithAuxSigner(auxSigner),
×
398
        )
×
399
        if err != nil {
×
400
                return nil, nil, err
×
401
        }
×
402
        bobPool.Start()
×
403
        t.Cleanup(func() {
×
404
                require.NoError(t, bobPool.Stop())
×
405
        })
×
406

407
        err = SetStateNumHint(
×
408
                aliceCommitTx, 0, obfuscator,
×
409
        )
×
410
        if err != nil {
×
411
                return nil, nil, err
×
412
        }
×
413
        err = SetStateNumHint(
×
414
                bobCommitTx, 0, obfuscator,
×
415
        )
×
416
        if err != nil {
×
417
                return nil, nil, err
×
418
        }
×
419

420
        addr := &net.TCPAddr{
×
421
                IP:   net.ParseIP("127.0.0.1"),
×
422
                Port: 18556,
×
423
        }
×
424
        if err := channelAlice.channelState.SyncPending(addr, 101); err != nil {
×
425
                return nil, nil, err
×
426
        }
×
427

428
        addr = &net.TCPAddr{
×
429
                IP:   net.ParseIP("127.0.0.1"),
×
430
                Port: 18555,
×
431
        }
×
432

×
433
        if err := channelBob.channelState.SyncPending(addr, 101); err != nil {
×
434
                return nil, nil, err
×
435
        }
×
436

437
        // Now that the channel are open, simulate the start of a session by
438
        // having Alice and Bob extend their revocation windows to each other.
439
        err = initRevocationWindows(channelAlice, channelBob)
×
440
        if err != nil {
×
441
                return nil, nil, err
×
442
        }
×
443

444
        return channelAlice, channelBob, nil
×
445
}
446

447
// initMusigNonce is used to manually setup musig2 nonces for a new channel,
448
// outside the normal chan-reest flow.
449
func initMusigNonce(chanA, chanB *LightningChannel) error {
×
450
        chanANonces, err := chanA.GenMusigNonces()
×
451
        if err != nil {
×
452
                return err
×
453
        }
×
454
        chanBNonces, err := chanB.GenMusigNonces()
×
455
        if err != nil {
×
456
                return err
×
457
        }
×
458

459
        if err := chanA.InitRemoteMusigNonces(chanBNonces); err != nil {
×
460
                return err
×
461
        }
×
462
        if err := chanB.InitRemoteMusigNonces(chanANonces); err != nil {
×
463
                return err
×
464
        }
×
465

466
        return nil
×
467
}
468

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

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

490
        bobNextRevoke, err := chanB.NextRevocationKey()
×
491
        if err != nil {
×
492
                return err
×
493
        }
×
494
        if err := chanA.InitNextRevocation(bobNextRevoke); err != nil {
×
495
                return err
×
496
        }
×
497

498
        return nil
×
499
}
500

501
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
502
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
×
503
        bytes, err := hex.DecodeString(keyHex)
×
504
        if err != nil {
×
505
                return nil, err
×
506
        }
×
507
        return btcec.ParsePubKey(bytes)
×
508
}
509

510
// privkeyFromHex parses a Bitcoin private key from a hex encoded string.
511
func privkeyFromHex(keyHex string) (*btcec.PrivateKey, error) {
×
512
        bytes, err := hex.DecodeString(keyHex)
×
513
        if err != nil {
×
514
                return nil, err
×
515
        }
×
516
        key, _ := btcec.PrivKeyFromBytes(bytes)
×
517
        return key, nil
×
518

519
}
520

521
// blockFromHex parses a full Bitcoin block from a hex encoded string.
522
func blockFromHex(blockHex string) (*btcutil.Block, error) {
×
523
        bytes, err := hex.DecodeString(blockHex)
×
524
        if err != nil {
×
525
                return nil, err
×
526
        }
×
527
        return btcutil.NewBlockFromBytes(bytes)
×
528
}
529

530
// txFromHex parses a full Bitcoin transaction from a hex encoded string.
531
func txFromHex(txHex string) (*btcutil.Tx, error) {
×
532
        bytes, err := hex.DecodeString(txHex)
×
533
        if err != nil {
×
534
                return nil, err
×
535
        }
×
536
        return btcutil.NewTxFromBytes(bytes)
×
537
}
538

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

×
552
        return feePerKw * (btcutil.Amount(totalWeight)) / 1000
×
553
}
×
554

555
// ForceStateTransition executes the necessary interaction between the two
556
// commitment state machines to transition to a new state locking in any
557
// pending updates. This method is useful when testing interactions between two
558
// live state machines.
559
func ForceStateTransition(chanA, chanB *LightningChannel) error {
×
560
        aliceNewCommit, err := chanA.SignNextCommitment()
×
561
        if err != nil {
×
562
                return err
×
563
        }
×
564
        err = chanB.ReceiveNewCommitment(aliceNewCommit.CommitSigs)
×
565
        if err != nil {
×
566
                return err
×
567
        }
×
568

569
        bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
×
570
        if err != nil {
×
571
                return err
×
572
        }
×
573
        bobNewCommit, err := chanB.SignNextCommitment()
×
574
        if err != nil {
×
575
                return err
×
576
        }
×
577

578
        _, _, err = chanA.ReceiveRevocation(bobRevocation)
×
579
        if err != nil {
×
580
                return err
×
581
        }
×
582
        err = chanA.ReceiveNewCommitment(bobNewCommit.CommitSigs)
×
583
        if err != nil {
×
584
                return err
×
585
        }
×
586

587
        aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
×
588
        if err != nil {
×
589
                return err
×
590
        }
×
591
        _, _, err = chanB.ReceiveRevocation(aliceRevocation)
×
592
        if err != nil {
×
593
                return err
×
594
        }
×
595

596
        return nil
×
597
}
598

599
func NewDefaultAuxSignerMock(t *testing.T) *MockAuxSigner {
×
600
        auxSigner := &MockAuxSigner{}
×
601

×
602
        type testSigBlob struct {
×
603
                BlobInt tlv.RecordT[tlv.TlvType65634, uint16]
×
604
        }
×
605

×
606
        var sigBlobBuf bytes.Buffer
×
607
        sigBlob := testSigBlob{
×
608
                BlobInt: tlv.NewPrimitiveRecord[tlv.TlvType65634, uint16](5),
×
609
        }
×
610
        tlvStream, err := tlv.NewStream(sigBlob.BlobInt.Record())
×
611
        require.NoError(t, err, "unable to create tlv stream")
×
612
        require.NoError(t, tlvStream.Encode(&sigBlobBuf))
×
613

×
614
        auxSigner.On(
×
615
                "SubmitSecondLevelSigBatch", mock.Anything, mock.Anything,
×
616
                mock.Anything,
×
617
        ).Return(nil)
×
618
        auxSigner.On(
×
619
                "PackSigs", mock.Anything,
×
620
        ).Return(fn.Ok(fn.Some(sigBlobBuf.Bytes())))
×
621
        auxSigner.On(
×
622
                "UnpackSigs", mock.Anything,
×
623
        ).Return(fn.Ok([]fn.Option[tlv.Blob]{
×
624
                fn.Some(sigBlobBuf.Bytes()),
×
625
        }))
×
626
        auxSigner.On(
×
627
                "VerifySecondLevelSigs", mock.Anything, mock.Anything,
×
628
                mock.Anything,
×
629
        ).Return(nil)
×
630

×
631
        return auxSigner
×
632
}
×
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