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

lightningnetwork / lnd / 11216766535

07 Oct 2024 01:37PM UTC coverage: 57.817% (-1.0%) from 58.817%
11216766535

Pull #9148

github

ProofOfKeags
lnwire: remove kickoff feerate from propose/commit
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

571 of 879 new or added lines in 16 files covered. (64.96%)

23253 existing lines in 251 files now uncovered.

99022 of 171268 relevant lines covered (57.82%)

38420.67 hits per line

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

93.17
/invoices/test_utils.go
1
package invoices
2

3
import (
4
        "crypto/rand"
5
        "encoding/binary"
6
        "encoding/hex"
7
        "fmt"
8
        "sync"
9
        "testing"
10
        "time"
11

12
        "github.com/btcsuite/btcd/btcec/v2"
13
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
14
        "github.com/btcsuite/btcd/chaincfg"
15
        "github.com/btcsuite/btcd/chaincfg/chainhash"
16
        "github.com/lightningnetwork/lnd/chainntnfs"
17
        "github.com/lightningnetwork/lnd/clock"
18
        "github.com/lightningnetwork/lnd/lntypes"
19
        "github.com/lightningnetwork/lnd/lnwire"
20
        "github.com/lightningnetwork/lnd/zpay32"
21
        "github.com/stretchr/testify/require"
22
)
23

24
type mockChainNotifier struct {
25
        chainntnfs.ChainNotifier
26

27
        blockChan chan *chainntnfs.BlockEpoch
28
}
29

9✔
30
func newMockNotifier() *mockChainNotifier {
9✔
31
        return &mockChainNotifier{
9✔
32
                blockChan: make(chan *chainntnfs.BlockEpoch),
9✔
33
        }
9✔
34
}
35

36
// RegisterBlockEpochNtfn mocks a block epoch notification, using the mock's
37
// block channel to deliver blocks to the client.
38
func (m *mockChainNotifier) RegisterBlockEpochNtfn(*chainntnfs.BlockEpoch) (
10✔
39
        *chainntnfs.BlockEpochEvent, error) {
10✔
40

10✔
41
        return &chainntnfs.BlockEpochEvent{
10✔
42
                Epochs: m.blockChan,
20✔
43
                Cancel: func() {},
44
        }, nil
45
}
46

47
const (
48
        testCurrentHeight = int32(1)
49
)
50

51
var (
52
        testTimeout = 5 * time.Second
53

54
        testTime = time.Date(2018, time.February, 2, 14, 0, 0, 0, time.UTC)
55

56
        testPrivKeyBytes, _ = hex.DecodeString(
57
                "e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2d" +
58
                        "b734",
59
        )
60

61
        testPrivKey, _ = btcec.PrivKeyFromBytes(testPrivKeyBytes)
62

63
        testInvoiceDescription = "coffee"
64

65
        testInvoiceAmount = lnwire.MilliSatoshi(100000)
66

67
        testNetParams = &chaincfg.MainNetParams
68

69
        testMessageSigner = zpay32.MessageSigner{
29✔
70
                SignCompact: func(msg []byte) ([]byte, error) {
29✔
71
                        hash := chainhash.HashB(msg)
29✔
72
                        sig, err := ecdsa.SignCompact(testPrivKey, hash, true)
29✔
73
                        if err != nil {
29✔
74
                                return nil, fmt.Errorf("can't sign the "+
29✔
75
                                        "message: %v", err)
76
                        }
77

78
                        return sig, nil
79
                },
80
        }
81

82
        testFeatures = lnwire.NewFeatureVector(
83
                nil, lnwire.Features,
29✔
84
        )
29✔
85
)
29✔
86

29✔
87
func newTestInvoice(t *testing.T, preimage lntypes.Preimage,
29✔
UNCOV
88
        timestamp time.Time, expiry time.Duration) *Invoice {
×
UNCOV
89

×
90
        t.Helper()
91

29✔
92
        if expiry == 0 {
29✔
93
                expiry = time.Hour
×
94
        }
×
95

96
        var payAddr [32]byte
29✔
97
        if _, err := rand.Read(payAddr[:]); err != nil {
29✔
98
                t.Fatalf("unable to generate payment addr: %v", err)
29✔
99
        }
29✔
100

29✔
101
        rawInvoice, err := zpay32.NewInvoice(
29✔
102
                testNetParams,
29✔
103
                preimage.Hash(),
29✔
104
                timestamp,
29✔
105
                zpay32.Amount(testInvoiceAmount),
29✔
106
                zpay32.Description(testInvoiceDescription),
29✔
107
                zpay32.Expiry(expiry),
29✔
108
                zpay32.PaymentAddr(payAddr),
29✔
109
        )
29✔
110
        require.NoError(t, err, "Error while creating new invoice")
29✔
111

29✔
112
        paymentRequest, err := rawInvoice.Encode(testMessageSigner)
29✔
113

29✔
114
        require.NoError(t, err, "Error while encoding payment request")
29✔
115

29✔
116
        return &Invoice{
29✔
117
                Terms: ContractTerm{
29✔
118
                        PaymentPreimage: &preimage,
29✔
119
                        PaymentAddr:     payAddr,
29✔
120
                        Value:           testInvoiceAmount,
29✔
121
                        Expiry:          expiry,
29✔
122
                        Features:        testFeatures,
123
                },
124
                PaymentRequest: []byte(paymentRequest),
125
                CreationDate:   timestamp,
126
        }
127
}
128

129
// invoiceExpiryTestData simply holds generated expired and pending invoices.
130
type invoiceExpiryTestData struct {
131
        expiredInvoices map[lntypes.Hash]*Invoice
132
        pendingInvoices map[lntypes.Hash]*Invoice
133
}
134

4✔
135
// generateInvoiceExpiryTestData generates the specified number of fake expired
4✔
136
// and pending invoices anchored to the passed now timestamp.
4✔
137
func generateInvoiceExpiryTestData(
4✔
138
        t *testing.T, now time.Time,
4✔
139
        offset, numExpired, numPending int) invoiceExpiryTestData {
4✔
140

4✔
141
        t.Helper()
4✔
142

4✔
143
        var testData invoiceExpiryTestData
4✔
144

4✔
145
        testData.expiredInvoices = make(map[lntypes.Hash]*Invoice)
14✔
146
        testData.pendingInvoices = make(map[lntypes.Hash]*Invoice)
10✔
147

10✔
148
        expiredCreationDate := now.Add(-24 * time.Hour)
10✔
149

10✔
150
        for i := 1; i <= numExpired; i++ {
10✔
151
                var preimage lntypes.Preimage
10✔
152
                binary.BigEndian.PutUint32(preimage[:4], uint32(offset+i))
10✔
153
                duration := (i + offset) % 24
10✔
154
                expiry := time.Duration(duration) * time.Hour
10✔
155
                invoice := newTestInvoice(
156
                        t, preimage, expiredCreationDate, expiry,
19✔
157
                )
15✔
158
                testData.expiredInvoices[preimage.Hash()] = invoice
15✔
159
        }
15✔
160

15✔
161
        for i := 1; i <= numPending; i++ {
15✔
162
                var preimage lntypes.Preimage
15✔
163
                binary.BigEndian.PutUint32(preimage[4:], uint32(offset+i))
15✔
164
                duration := (i + offset) % 24
165
                expiry := time.Duration(duration) * time.Hour
4✔
166
                invoice := newTestInvoice(t, preimage, now, expiry)
167
                testData.pendingInvoices[preimage.Hash()] = invoice
168
        }
169

170
        return testData
171
}
172

173
type hodlExpiryTest struct {
174
        hash         lntypes.Hash
175
        state        ContractState
176
        stateLock    sync.Mutex
177
        mockNotifier *mockChainNotifier
178
        mockClock    *clock.TestClock
1✔
179
        cancelChan   chan lntypes.Hash
1✔
180
        watcher      *InvoiceExpiryWatcher
1✔
181
}
1✔
182

1✔
183
func (h *hodlExpiryTest) setState(state ContractState) {
1✔
184
        h.stateLock.Lock()
185
        defer h.stateLock.Unlock()
2✔
186

2✔
187
        h.state = state
2✔
188
}
2✔
189

190
func (h *hodlExpiryTest) announceBlock(t *testing.T, height uint32) {
191
        t.Helper()
2✔
192

UNCOV
193
        select {
×
UNCOV
194
        case h.mockNotifier.blockChan <- &chainntnfs.BlockEpoch{
×
195
                Height: int32(height),
196
        }:
197

198
        case <-time.After(testTimeout):
4✔
199
                t.Fatalf("block %v not consumed", height)
4✔
200
        }
4✔
201
}
4✔
202

4✔
203
func (h *hodlExpiryTest) assertCanceled(t *testing.T, expected lntypes.Hash) {
4✔
204
        t.Helper()
UNCOV
205

×
UNCOV
206
        select {
×
207
        case actual := <-h.cancelChan:
208
                require.Equal(t, expected, actual)
209

210
        case <-time.After(testTimeout):
211
                t.Fatalf("invoice: %v not canceled", h.hash)
212
        }
213
}
214

215
// setupHodlExpiry creates a hodl invoice in our expiry watcher and runs an
4✔
216
// arbitrary update function which advances the invoices's state.
4✔
217
func setupHodlExpiry(t *testing.T, creationDate time.Time,
4✔
218
        expiry time.Duration, heightDelta uint32,
4✔
219
        startState ContractState,
4✔
220
        startHtlcs []*InvoiceHTLC) *hodlExpiryTest {
4✔
221

4✔
222
        t.Helper()
4✔
223

4✔
224
        mockNotifier := newMockNotifier()
4✔
225
        mockClock := clock.NewTestClock(testTime)
4✔
226

4✔
227
        test := &hodlExpiryTest{
4✔
228
                state: startState,
4✔
229
                watcher: NewInvoiceExpiryWatcher(
4✔
230
                        mockClock, heightDelta, uint32(testCurrentHeight), nil,
4✔
231
                        mockNotifier,
4✔
232
                ),
4✔
233
                cancelChan:   make(chan lntypes.Hash),
4✔
234
                mockNotifier: mockNotifier,
4✔
235
                mockClock:    mockClock,
8✔
236
        }
4✔
237

4✔
238
        // Use an unbuffered channel to block on cancel calls so that the test
4✔
239
        // does not exit before we've processed all the invoices we expect.
4✔
240
        cancelImpl := func(paymentHash lntypes.Hash, force bool) error {
4✔
UNCOV
241
                test.stateLock.Lock()
×
UNCOV
242
                currentState := test.state
×
243
                test.stateLock.Unlock()
244

4✔
245
                if currentState != ContractOpen && !force {
4✔
246
                        return nil
×
247
                }
248

249
                select {
4✔
250
                case test.cancelChan <- paymentHash:
251
                case <-time.After(testTimeout):
252
                }
4✔
253

4✔
254
                return nil
4✔
255
        }
4✔
256

4✔
257
        require.NoError(t, test.watcher.Start(cancelImpl))
4✔
258

4✔
259
        // We set preimage and hash so that we can use our existing test
4✔
260
        // helpers. In practice we would only have the hash, but this does not
4✔
261
        // affect what we're testing at all.
4✔
262
        preimage := lntypes.Preimage{1}
4✔
263
        test.hash = preimage.Hash()
4✔
264

4✔
265
        invoice := newTestInvoice(t, preimage, creationDate, expiry)
4✔
266
        invoice.State = startState
5✔
267
        invoice.HodlInvoice = true
1✔
268
        invoice.Htlcs = make(map[CircuitKey]*InvoiceHTLC)
1✔
269

1✔
270
        // If we have any htlcs, add them with unique circult keys.
1✔
271
        for i, htlc := range startHtlcs {
1✔
272
                key := CircuitKey{
1✔
273
                        HtlcID: uint64(i),
274
                }
275

276
                invoice.Htlcs[key] = htlc
4✔
277
        }
4✔
278

4✔
279
        // Create an expiry entry for our invoice in its starting state. This
4✔
280
        // mimics adding invoices to the watcher on start.
281
        entry := makeInvoiceExpiry(test.hash, invoice)
282
        test.watcher.AddInvoices(entry)
283

284
        return test
285
}
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