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

lightningnetwork / lnd / 15754665794

19 Jun 2025 09:36AM UTC coverage: 68.186% (+0.03%) from 68.161%
15754665794

Pull #9880

github

web-flow
Merge bdc6e10a2 into e0a9705d5
Pull Request #9880: Improve access control in peer connections

201 of 249 new or added lines in 7 files covered. (80.72%)

75 existing lines in 24 files now uncovered.

134637 of 197455 relevant lines covered (68.19%)

22116.57 hits per line

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

0.0
/lntest/harness_assertion.go
1
package lntest
2

3
import (
4
        "bytes"
5
        "context"
6
        "crypto/rand"
7
        "encoding/hex"
8
        "encoding/json"
9
        "fmt"
10
        "math"
11
        "sort"
12
        "strings"
13
        "time"
14

15
        "github.com/btcsuite/btcd/btcec/v2"
16
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
17
        "github.com/btcsuite/btcd/btcutil"
18
        "github.com/btcsuite/btcd/chaincfg/chainhash"
19
        "github.com/btcsuite/btcd/txscript"
20
        "github.com/btcsuite/btcd/wire"
21
        "github.com/lightningnetwork/lnd/channeldb"
22
        "github.com/lightningnetwork/lnd/lnrpc"
23
        "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
24
        "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
25
        "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
26
        "github.com/lightningnetwork/lnd/lntest/miner"
27
        "github.com/lightningnetwork/lnd/lntest/node"
28
        "github.com/lightningnetwork/lnd/lntest/rpc"
29
        "github.com/lightningnetwork/lnd/lntest/wait"
30
        "github.com/lightningnetwork/lnd/lntypes"
31
        "github.com/lightningnetwork/lnd/lnutils"
32
        "github.com/stretchr/testify/require"
33
        "google.golang.org/protobuf/proto"
34
)
35

36
// FindChannelOption is a functional type for an option that modifies a
37
// ListChannelsRequest.
38
type ListChannelOption func(r *lnrpc.ListChannelsRequest)
39

40
// WithPeerAliasLookup is an option for setting the peer alias lookup flag on a
41
// ListChannelsRequest.
42
func WithPeerAliasLookup() ListChannelOption {
×
43
        return func(r *lnrpc.ListChannelsRequest) {
×
44
                r.PeerAliasLookup = true
×
45
        }
×
46
}
47

48
// WaitForBlockchainSync waits until the node is synced to chain.
49
func (h *HarnessTest) WaitForBlockchainSync(hn *node.HarnessNode) {
×
50
        err := wait.NoError(func() error {
×
51
                resp := hn.RPC.GetInfo()
×
52
                if resp.SyncedToChain {
×
53
                        return nil
×
54
                }
×
55

56
                return fmt.Errorf("%s is not synced to chain", hn.Name())
×
57
        }, DefaultTimeout)
58

59
        require.NoError(h, err, "timeout waiting for blockchain sync")
×
60
}
61

62
// WaitForBlockchainSyncTo waits until the node is synced to bestBlock.
63
func (h *HarnessTest) WaitForBlockchainSyncTo(hn *node.HarnessNode,
64
        bestBlock chainhash.Hash) {
×
65

×
66
        bestBlockHash := bestBlock.String()
×
67
        err := wait.NoError(func() error {
×
68
                resp := hn.RPC.GetInfo()
×
69
                if resp.SyncedToChain {
×
70
                        if resp.BlockHash == bestBlockHash {
×
71
                                return nil
×
72
                        }
×
73

74
                        return fmt.Errorf("%s's backend is synced to the "+
×
75
                                "wrong block (expected=%s, actual=%s)",
×
76
                                hn.Name(), bestBlockHash, resp.BlockHash)
×
77
                }
78

79
                return fmt.Errorf("%s is not synced to chain", hn.Name())
×
80
        }, DefaultTimeout)
81

82
        require.NoError(h, err, "timeout waiting for blockchain sync")
×
83
}
84

85
// AssertPeerConnected asserts that the given node b is connected to a.
86
func (h *HarnessTest) AssertPeerConnected(a, b *node.HarnessNode) {
×
87
        err := wait.NoError(func() error {
×
88
                // We require the RPC call to be succeeded and won't wait for
×
89
                // it as it's an unexpected behavior.
×
90
                resp := a.RPC.ListPeers()
×
91

×
92
                // If node B is seen in the ListPeers response from node A,
×
93
                // then we can return true as the connection has been fully
×
94
                // established.
×
95
                for _, peer := range resp.Peers {
×
96
                        if peer.PubKey == b.PubKeyStr {
×
97
                                return nil
×
98
                        }
×
99
                }
100

101
                return fmt.Errorf("%s not found in %s's ListPeers",
×
102
                        b.Name(), a.Name())
×
103
        }, DefaultTimeout)
104

105
        require.NoError(h, err, "unable to connect %s to %s, got error: "+
×
106
                "peers not connected within %v seconds",
×
107
                a.Name(), b.Name(), DefaultTimeout)
×
108
}
109

110
// ConnectNodes creates a connection between the two nodes and asserts the
111
// connection is succeeded.
112
func (h *HarnessTest) ConnectNodes(a, b *node.HarnessNode) {
×
113
        bobInfo := b.RPC.GetInfo()
×
114

×
115
        req := &lnrpc.ConnectPeerRequest{
×
116
                Addr: &lnrpc.LightningAddress{
×
117
                        Pubkey: bobInfo.IdentityPubkey,
×
118
                        Host:   b.Cfg.P2PAddr(),
×
119
                },
×
120
        }
×
121
        a.RPC.ConnectPeer(req)
×
NEW
122
        h.AssertConnected(a, b)
×
123
}
×
124

125
// ConnectNodesPerm creates a persistent connection between the two nodes and
126
// asserts the connection is succeeded.
127
func (h *HarnessTest) ConnectNodesPerm(a, b *node.HarnessNode) {
×
128
        bobInfo := b.RPC.GetInfo()
×
129

×
130
        req := &lnrpc.ConnectPeerRequest{
×
131
                Addr: &lnrpc.LightningAddress{
×
132
                        Pubkey: bobInfo.IdentityPubkey,
×
133
                        Host:   b.Cfg.P2PAddr(),
×
134
                },
×
135
                Perm: true,
×
136
        }
×
137
        a.RPC.ConnectPeer(req)
×
138
        h.AssertPeerConnected(a, b)
×
139
}
×
140

141
// DisconnectNodes disconnects the given two nodes and asserts the
142
// disconnection is succeeded. The request is made from node a and sent to node
143
// b.
144
func (h *HarnessTest) DisconnectNodes(a, b *node.HarnessNode) {
×
145
        bobInfo := b.RPC.GetInfo()
×
146
        a.RPC.DisconnectPeer(bobInfo.IdentityPubkey)
×
147

×
148
        // Assert disconnected.
×
149
        h.AssertPeerNotConnected(a, b)
×
150
}
×
151

152
// EnsureConnected will try to connect to two nodes, returning no error if they
153
// are already connected. If the nodes were not connected previously, this will
154
// behave the same as ConnectNodes. If a pending connection request has already
155
// been made, the method will block until the two nodes appear in each other's
156
// peers list, or until the DefaultTimeout expires.
157
func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
×
158
        // errConnectionRequested is used to signal that a connection was
×
159
        // requested successfully, which is distinct from already being
×
160
        // connected to the peer.
×
161
        errConnectionRequested := "connection request in progress"
×
162

×
163
        // windowsErr is an error we've seen from windows build where
×
164
        // connecting to an already connected node gives such error from the
×
165
        // receiver side.
×
166
        windowsErr := "An established connection was aborted by the software " +
×
167
                "in your host machine."
×
168

×
169
        tryConnect := func(a, b *node.HarnessNode) error {
×
170
                bInfo := b.RPC.GetInfo()
×
171

×
172
                req := &lnrpc.ConnectPeerRequest{
×
173
                        Addr: &lnrpc.LightningAddress{
×
174
                                Pubkey: bInfo.IdentityPubkey,
×
175
                                Host:   b.Cfg.P2PAddr(),
×
176
                        },
×
177
                }
×
178

×
179
                ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
×
180
                defer cancel()
×
181

×
182
                _, err := a.RPC.LN.ConnectPeer(ctxt, req)
×
183

×
184
                // Request was successful.
×
185
                if err == nil {
×
186
                        return nil
×
187
                }
×
188

189
                // If the two are already connected, we return early with no
190
                // error.
191
                if strings.Contains(err.Error(), "already connected to peer") {
×
192
                        return nil
×
193
                }
×
194

195
                // Otherwise we log the error to console.
196
                h.Logf("EnsureConnected %s=>%s got err: %v", a.Name(),
×
197
                        b.Name(), err)
×
198

×
199
                // If the connection is in process, we return no error.
×
200
                if strings.Contains(err.Error(), errConnectionRequested) {
×
201
                        return nil
×
202
                }
×
203

204
                // We may get connection refused error if we happens to be in
205
                // the middle of a previous node disconnection, e.g., a restart
206
                // from one of the nodes.
207
                if strings.Contains(err.Error(), "connection refused") {
×
208
                        return nil
×
209
                }
×
210

211
                // Check for windows error. If Alice connects to Bob, Alice
212
                // will throw "i/o timeout" and Bob will give windowsErr.
213
                if strings.Contains(err.Error(), windowsErr) {
×
214
                        return nil
×
215
                }
×
216

217
                if strings.Contains(err.Error(), "i/o timeout") {
×
218
                        return nil
×
219
                }
×
220

221
                return err
×
222
        }
223

224
        // Return any critical errors returned by either alice or bob.
225
        require.NoError(h, tryConnect(a, b), "connection failed between %s "+
×
226
                "and %s", a.Cfg.Name, b.Cfg.Name)
×
227

×
228
        // When Alice and Bob each makes a connection to the other side at the
×
229
        // same time, it's likely neither connections could succeed. Bob's
×
230
        // connection will be canceled by Alice since she has an outbound
×
231
        // connection to Bob already, and same happens to Alice's. Thus the two
×
232
        // connections cancel each other out.
×
233
        // TODO(yy): move this back when the above issue is fixed.
×
234
        // require.NoError(h, tryConnect(b, a), "connection failed between %s "+
×
235
        //         "and %s", a.Cfg.Name, b.Cfg.Name)
×
236

×
237
        // Otherwise one or both requested a connection, so we wait for the
×
238
        // peers lists to reflect the connection.
×
239
        h.AssertPeerConnected(a, b)
×
240
        h.AssertPeerConnected(b, a)
×
241
}
242

243
// ConnectNodesNoAssert creates a connection from node A to node B.
244
func (h *HarnessTest) ConnectNodesNoAssert(a, b *node.HarnessNode) (
NEW
245
        *lnrpc.ConnectPeerResponse, error) {
×
NEW
246

×
NEW
247
        bobInfo := b.RPC.GetInfo()
×
NEW
248

×
NEW
249
        req := &lnrpc.ConnectPeerRequest{
×
NEW
250
                Addr: &lnrpc.LightningAddress{
×
NEW
251
                        Pubkey: bobInfo.IdentityPubkey,
×
NEW
252
                        Host:   b.Cfg.P2PAddr(),
×
NEW
253
                },
×
NEW
254
        }
×
NEW
255
        ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
×
NEW
256
        defer cancel()
×
NEW
257

×
NEW
258
        return a.RPC.LN.ConnectPeer(ctxt, req)
×
NEW
259
}
×
260

261
// AssertNumEdges checks that an expected number of edges can be found in the
262
// node specified.
263
func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode,
264
        expected int, includeUnannounced bool) []*lnrpc.ChannelEdge {
×
265

×
266
        var edges []*lnrpc.ChannelEdge
×
267

×
268
        old := hn.State.Edge.Public
×
269
        if includeUnannounced {
×
270
                old = hn.State.Edge.Total
×
271
        }
×
272

273
        err := wait.NoError(func() error {
×
274
                req := &lnrpc.ChannelGraphRequest{
×
275
                        IncludeUnannounced: includeUnannounced,
×
276
                }
×
277
                resp := hn.RPC.DescribeGraph(req)
×
278
                total := len(resp.Edges)
×
279

×
280
                if total-old == expected {
×
281
                        if expected != 0 {
×
282
                                // NOTE: assume edges come in ascending order
×
283
                                // that the old edges are at the front of the
×
284
                                // slice.
×
285
                                edges = resp.Edges[old:]
×
286
                        }
×
287

288
                        return nil
×
289
                }
290

291
                return errNumNotMatched(hn.Name(), "num of channel edges",
×
292
                        expected, total-old, total, old)
×
293
        }, DefaultTimeout)
294

295
        require.NoError(h, err, "timeout while checking for edges")
×
296

×
297
        return edges
×
298
}
299

300
// ReceiveOpenChannelUpdate waits until a message is received on the stream or
301
// the timeout is reached.
302
func (h *HarnessTest) ReceiveOpenChannelUpdate(
303
        stream rpc.OpenChanClient) *lnrpc.OpenStatusUpdate {
×
304

×
305
        update, err := h.receiveOpenChannelUpdate(stream)
×
306
        require.NoError(h, err, "received err from open channel stream")
×
307

×
308
        return update
×
309
}
×
310

311
// ReceiveOpenChannelError waits for the expected error during the open channel
312
// flow from the peer or times out.
313
func (h *HarnessTest) ReceiveOpenChannelError(
314
        stream rpc.OpenChanClient, expectedErr error) {
×
315

×
316
        _, err := h.receiveOpenChannelUpdate(stream)
×
317
        require.Contains(h, err.Error(), expectedErr.Error(),
×
318
                "error not matched")
×
319
}
×
320

321
// receiveOpenChannelUpdate waits until a message or an error is received on
322
// the stream or the timeout is reached.
323
//
324
// TODO(yy): use generics to unify all receiving stream update once go@1.18 is
325
// used.
326
func (h *HarnessTest) receiveOpenChannelUpdate(
327
        stream rpc.OpenChanClient) (*lnrpc.OpenStatusUpdate, error) {
×
328

×
329
        chanMsg := make(chan *lnrpc.OpenStatusUpdate)
×
330
        errChan := make(chan error)
×
331
        go func() {
×
332
                // Consume one message. This will block until the message is
×
333
                // received.
×
334
                resp, err := stream.Recv()
×
335
                if err != nil {
×
336
                        errChan <- err
×
337
                        return
×
338
                }
×
339
                chanMsg <- resp
×
340
        }()
341

342
        select {
×
343
        case <-time.After(DefaultTimeout):
×
344
                require.Fail(h, "timeout", "timeout waiting for open channel "+
×
345
                        "update sent")
×
346
                return nil, nil
×
347

348
        case err := <-errChan:
×
349
                return nil, err
×
350

351
        case updateMsg := <-chanMsg:
×
352
                return updateMsg, nil
×
353
        }
354
}
355

356
// WaitForChannelOpenEvent waits for a notification that a channel is open by
357
// consuming a message from the passed open channel stream.
358
func (h HarnessTest) WaitForChannelOpenEvent(
359
        stream rpc.OpenChanClient) *lnrpc.ChannelPoint {
×
360

×
361
        // Consume one event.
×
362
        event := h.ReceiveOpenChannelUpdate(stream)
×
363

×
364
        resp, ok := event.Update.(*lnrpc.OpenStatusUpdate_ChanOpen)
×
365
        require.Truef(h, ok, "expected channel open update, instead got %v",
×
366
                resp)
×
367

×
368
        return resp.ChanOpen.ChannelPoint
×
369
}
×
370

371
// AssertChannelExists asserts that an active channel identified by the
372
// specified channel point exists from the point-of-view of the node.
373
func (h *HarnessTest) AssertChannelExists(hn *node.HarnessNode,
374
        cp *lnrpc.ChannelPoint) *lnrpc.Channel {
×
375

×
376
        return h.assertChannelStatus(hn, cp, true)
×
377
}
×
378

379
// AssertChannelActive checks if a channel identified by the specified channel
380
// point is active.
381
func (h *HarnessTest) AssertChannelActive(hn *node.HarnessNode,
382
        cp *lnrpc.ChannelPoint) *lnrpc.Channel {
×
383

×
384
        return h.assertChannelStatus(hn, cp, true)
×
385
}
×
386

387
// AssertChannelInactive checks if a channel identified by the specified channel
388
// point is inactive.
389
func (h *HarnessTest) AssertChannelInactive(hn *node.HarnessNode,
390
        cp *lnrpc.ChannelPoint) *lnrpc.Channel {
×
391

×
392
        return h.assertChannelStatus(hn, cp, false)
×
393
}
×
394

395
// assertChannelStatus asserts that a channel identified by the specified
396
// channel point exists from the point-of-view of the node and that it is either
397
// active or inactive depending on the value of the active parameter.
398
func (h *HarnessTest) assertChannelStatus(hn *node.HarnessNode,
399
        cp *lnrpc.ChannelPoint, active bool) *lnrpc.Channel {
×
400

×
401
        var (
×
402
                channel *lnrpc.Channel
×
403
                err     error
×
404
        )
×
405

×
406
        err = wait.NoError(func() error {
×
407
                channel, err = h.findChannel(hn, cp)
×
408
                if err != nil {
×
409
                        return err
×
410
                }
×
411

412
                // Check whether the channel is active, exit early if it is.
413
                if channel.Active == active {
×
414
                        return nil
×
415
                }
×
416

417
                return fmt.Errorf("expected channel_active=%v, got %v",
×
418
                        active, channel.Active)
×
419
        }, DefaultTimeout)
420

421
        require.NoErrorf(h, err, "%s: timeout checking for channel point: %v",
×
422
                hn.Name(), h.OutPointFromChannelPoint(cp))
×
423

×
424
        return channel
×
425
}
426

427
// AssertOutputScriptClass checks that the specified transaction output has the
428
// expected script class.
429
func (h *HarnessTest) AssertOutputScriptClass(tx *btcutil.Tx,
430
        outputIndex uint32, scriptClass txscript.ScriptClass) {
×
431

×
432
        require.Greater(h, len(tx.MsgTx().TxOut), int(outputIndex))
×
433

×
434
        txOut := tx.MsgTx().TxOut[outputIndex]
×
435

×
436
        pkScript, err := txscript.ParsePkScript(txOut.PkScript)
×
437
        require.NoError(h, err)
×
438
        require.Equal(h, scriptClass, pkScript.Class())
×
439
}
×
440

441
// findChannel tries to find a target channel in the node using the given
442
// channel point.
443
func (h *HarnessTest) findChannel(hn *node.HarnessNode,
444
        chanPoint *lnrpc.ChannelPoint,
445
        opts ...ListChannelOption) (*lnrpc.Channel, error) {
×
446

×
447
        // Get the funding point.
×
448
        fp := h.OutPointFromChannelPoint(chanPoint)
×
449

×
450
        req := &lnrpc.ListChannelsRequest{}
×
451

×
452
        for _, opt := range opts {
×
453
                opt(req)
×
454
        }
×
455

456
        channelInfo := hn.RPC.ListChannels(req)
×
457

×
458
        // Find the target channel.
×
459
        for _, channel := range channelInfo.Channels {
×
460
                if channel.ChannelPoint == fp.String() {
×
461
                        return channel, nil
×
462
                }
×
463
        }
464

465
        return nil, fmt.Errorf("%s: channel not found using %s", hn.Name(),
×
466
                fp.String())
×
467
}
468

469
// ReceiveCloseChannelUpdate waits until a message or an error is received on
470
// the subscribe channel close stream or the timeout is reached.
471
func (h *HarnessTest) ReceiveCloseChannelUpdate(
472
        stream rpc.CloseChanClient) (*lnrpc.CloseStatusUpdate, error) {
×
473

×
474
        chanMsg := make(chan *lnrpc.CloseStatusUpdate)
×
475
        errChan := make(chan error)
×
476
        go func() {
×
477
                // Consume one message. This will block until the message is
×
478
                // received.
×
479
                resp, err := stream.Recv()
×
480
                if err != nil {
×
481
                        errChan <- err
×
482
                        return
×
483
                }
×
484
                chanMsg <- resp
×
485
        }()
486

487
        select {
×
488
        case <-time.After(DefaultTimeout):
×
489
                require.Fail(h, "timeout", "timeout waiting for close channel "+
×
490
                        "update sent")
×
491

×
492
                return nil, nil
×
493

494
        case err := <-errChan:
×
495
                return nil, fmt.Errorf("received err from close channel "+
×
496
                        "stream: %v", err)
×
497

498
        case updateMsg := <-chanMsg:
×
499
                return updateMsg, nil
×
500
        }
501
}
502

503
type WaitingCloseChannel *lnrpc.PendingChannelsResponse_WaitingCloseChannel
504

505
// AssertChannelWaitingClose asserts that the given channel found in the node
506
// is waiting close. Returns the WaitingCloseChannel if found.
507
func (h *HarnessTest) AssertChannelWaitingClose(hn *node.HarnessNode,
508
        chanPoint *lnrpc.ChannelPoint) WaitingCloseChannel {
×
509

×
510
        var target WaitingCloseChannel
×
511

×
512
        op := h.OutPointFromChannelPoint(chanPoint)
×
513

×
514
        err := wait.NoError(func() error {
×
515
                resp := hn.RPC.PendingChannels()
×
516

×
517
                for _, waitingClose := range resp.WaitingCloseChannels {
×
518
                        if waitingClose.Channel.ChannelPoint == op.String() {
×
519
                                target = waitingClose
×
520
                                return nil
×
521
                        }
×
522
                }
523

524
                return fmt.Errorf("%v: channel %s not found in waiting close",
×
525
                        hn.Name(), op)
×
526
        }, DefaultTimeout)
527
        require.NoError(h, err, "assert channel waiting close timed out")
×
528

×
529
        return target
×
530
}
531

532
// AssertTopologyChannelClosed asserts a given channel is closed by checking
533
// the graph topology subscription of the specified node. Returns the closed
534
// channel update if found.
535
func (h *HarnessTest) AssertTopologyChannelClosed(hn *node.HarnessNode,
536
        chanPoint *lnrpc.ChannelPoint) *lnrpc.ClosedChannelUpdate {
×
537

×
538
        closedChan, err := hn.Watcher.WaitForChannelClose(chanPoint)
×
539
        require.NoError(h, err, "failed to wait for channel close")
×
540

×
541
        return closedChan
×
542
}
×
543

544
// WaitForChannelCloseEvent waits for a notification that a channel is closed
545
// by consuming a message from the passed close channel stream. Returns the
546
// closing txid if found.
547
func (h HarnessTest) WaitForChannelCloseEvent(
548
        stream rpc.CloseChanClient) chainhash.Hash {
×
549

×
550
        // Consume one event.
×
551
        event, err := h.ReceiveCloseChannelUpdate(stream)
×
552
        require.NoError(h, err)
×
553

×
554
        resp, ok := event.Update.(*lnrpc.CloseStatusUpdate_ChanClose)
×
555
        require.Truef(h, ok, "expected channel close update, instead got %v",
×
556
                event.Update)
×
557

×
558
        txid, err := chainhash.NewHash(resp.ChanClose.ClosingTxid)
×
559
        require.NoErrorf(h, err, "wrong format found in closing txid: %v",
×
560
                resp.ChanClose.ClosingTxid)
×
561

×
562
        return *txid
×
563
}
×
564

565
// AssertNumWaitingClose checks that a PendingChannels response from the node
566
// reports the expected number of waiting close channels.
567
func (h *HarnessTest) AssertNumWaitingClose(hn *node.HarnessNode,
568
        num int) []*lnrpc.PendingChannelsResponse_WaitingCloseChannel {
×
569

×
570
        var channels []*lnrpc.PendingChannelsResponse_WaitingCloseChannel
×
571
        oldWaiting := hn.State.CloseChannel.WaitingClose
×
572

×
573
        err := wait.NoError(func() error {
×
574
                resp := hn.RPC.PendingChannels()
×
575
                channels = resp.WaitingCloseChannels
×
576
                total := len(channels)
×
577

×
578
                got := total - oldWaiting
×
579
                if got == num {
×
580
                        return nil
×
581
                }
×
582

583
                return errNumNotMatched(hn.Name(), "waiting close channels",
×
584
                        num, got, total, oldWaiting)
×
585
        }, DefaultTimeout)
586

587
        require.NoErrorf(h, err, "%s: assert waiting close timeout",
×
588
                hn.Name())
×
589

×
590
        return channels
×
591
}
592

593
// AssertNumPendingForceClose checks that a PendingChannels response from the
594
// node reports the expected number of pending force close channels.
595
func (h *HarnessTest) AssertNumPendingForceClose(hn *node.HarnessNode,
596
        num int) []*lnrpc.PendingChannelsResponse_ForceClosedChannel {
×
597

×
598
        var channels []*lnrpc.PendingChannelsResponse_ForceClosedChannel
×
599
        oldForce := hn.State.CloseChannel.PendingForceClose
×
600

×
601
        err := wait.NoError(func() error {
×
602
                // TODO(yy): we should be able to use `hn.RPC.PendingChannels`
×
603
                // here to avoid checking the RPC error. However, we may get a
×
604
                // `unable to find arbitrator` error from the rpc point, due to
×
605
                // a timing issue in rpcserver,
×
606
                // 1. `r.server.chanStateDB.FetchClosedChannels` fetches
×
607
                //    the pending force close channel.
×
608
                // 2. `r.arbitratorPopulateForceCloseResp` relies on the
×
609
                //    channel arbitrator to get the report, and,
×
610
                // 3. the arbitrator may be deleted due to the force close
×
611
                //    channel being resolved.
×
612
                // Somewhere along the line is missing a lock to keep the data
×
613
                // consistent.
×
614
                req := &lnrpc.PendingChannelsRequest{}
×
615
                resp, err := hn.RPC.LN.PendingChannels(h.runCtx, req)
×
616
                if err != nil {
×
617
                        return fmt.Errorf("PendingChannels got: %w", err)
×
618
                }
×
619

620
                channels = resp.PendingForceClosingChannels
×
621
                total := len(channels)
×
622

×
623
                got := total - oldForce
×
624
                if got == num {
×
625
                        return nil
×
626
                }
×
627

628
                return errNumNotMatched(hn.Name(), "pending force close "+
×
629
                        "channels", num, got, total, oldForce)
×
630
        }, DefaultTimeout)
631

632
        require.NoErrorf(h, err, "%s: assert pending force close timeout",
×
633
                hn.Name())
×
634

×
635
        return channels
×
636
}
637

638
// AssertStreamChannelCoopClosed reads an update from the close channel client
639
// stream and asserts that the mempool state and node's topology match a coop
640
// close. In specific,
641
// - assert the channel is waiting close and has the expected ChanStatusFlags.
642
// - assert the mempool has the closing txes and anchor sweeps.
643
// - mine a block and assert the closing txid is mined.
644
// - assert the node has zero waiting close channels.
645
// - assert the node has seen the channel close update.
646
func (h *HarnessTest) AssertStreamChannelCoopClosed(hn *node.HarnessNode,
647
        cp *lnrpc.ChannelPoint, anchors bool,
648
        stream rpc.CloseChanClient) chainhash.Hash {
×
649

×
650
        // Assert the channel is waiting close.
×
651
        resp := h.AssertChannelWaitingClose(hn, cp)
×
652

×
653
        // Assert that the channel is in coop broadcasted.
×
654
        require.Contains(h, resp.Channel.ChanStatusFlags,
×
655
                channeldb.ChanStatusCoopBroadcasted.String(),
×
656
                "channel not coop broadcasted")
×
657

×
658
        // We'll now, generate a single block, wait for the final close status
×
659
        // update, then ensure that the closing transaction was included in the
×
660
        // block. If there are anchors, we also expect an anchor sweep.
×
661
        expectedTxes := 1
×
662
        if anchors {
×
663
                expectedTxes = 2
×
664
        }
×
665
        block := h.MineBlocksAndAssertNumTxes(1, expectedTxes)[0]
×
666

×
667
        // Consume one close event and assert the closing txid can be found in
×
668
        // the block.
×
669
        closingTxid := h.WaitForChannelCloseEvent(stream)
×
670
        h.AssertTxInBlock(block, closingTxid)
×
671

×
672
        // We should see zero waiting close channels now.
×
673
        h.AssertNumWaitingClose(hn, 0)
×
674

×
675
        // Finally, check that the node's topology graph has seen this channel
×
676
        // closed if it's a public channel.
×
677
        if !resp.Channel.Private {
×
678
                h.AssertTopologyChannelClosed(hn, cp)
×
679
        }
×
680

681
        return closingTxid
×
682
}
683

684
// AssertStreamChannelForceClosed reads an update from the close channel client
685
// stream and asserts that the mempool state and node's topology match a local
686
// force close. In specific,
687
//   - assert the channel is waiting close and has the expected ChanStatusFlags.
688
//   - assert the mempool has the closing txes.
689
//   - mine a block and assert the closing txid is mined.
690
//   - assert the channel is pending force close.
691
//   - assert the node has seen the channel close update.
692
//   - assert there's a pending anchor sweep request once the force close tx is
693
//     confirmed.
694
func (h *HarnessTest) AssertStreamChannelForceClosed(hn *node.HarnessNode,
695
        cp *lnrpc.ChannelPoint, anchorSweep bool,
696
        stream rpc.CloseChanClient) chainhash.Hash {
×
697

×
698
        // Assert the channel is waiting close.
×
699
        resp := h.AssertChannelWaitingClose(hn, cp)
×
700

×
701
        // Assert that the channel is in local force broadcasted.
×
702
        require.Contains(h, resp.Channel.ChanStatusFlags,
×
703
                channeldb.ChanStatusLocalCloseInitiator.String(),
×
704
                "channel not coop broadcasted")
×
705

×
706
        // Get the closing txid.
×
707
        closeTxid, err := chainhash.NewHashFromStr(resp.ClosingTxid)
×
708
        require.NoError(h, err)
×
709

×
710
        // We'll now, generate a single block, wait for the final close status
×
711
        // update, then ensure that the closing transaction was included in the
×
712
        // block.
×
713
        closeTx := h.AssertTxInMempool(*closeTxid)
×
714
        h.MineBlockWithTx(closeTx)
×
715

×
716
        // Consume one close event and assert the closing txid can be found in
×
717
        // the block.
×
718
        closingTxid := h.WaitForChannelCloseEvent(stream)
×
719

×
720
        // We should see zero waiting close channels and 1 pending force close
×
721
        // channels now.
×
722
        h.AssertNumWaitingClose(hn, 0)
×
723
        h.AssertNumPendingForceClose(hn, 1)
×
724

×
725
        // Finally, check that the node's topology graph has seen this channel
×
726
        // closed if it's a public channel.
×
727
        if !resp.Channel.Private {
×
728
                h.AssertTopologyChannelClosed(hn, cp)
×
729
        }
×
730

731
        // Assert there's a pending anchor sweep.
732
        //
733
        // NOTE: We may have a local sweep here, that's why we use
734
        // AssertAtLeastNumPendingSweeps instead of AssertNumPendingSweeps.
735
        if anchorSweep {
×
736
                h.AssertAtLeastNumPendingSweeps(hn, 1)
×
737
        }
×
738

739
        return closingTxid
×
740
}
741

742
// AssertChannelPolicyUpdate checks that the required policy update has
743
// happened on the given node.
744
func (h *HarnessTest) AssertChannelPolicyUpdate(hn *node.HarnessNode,
745
        advertisingNode *node.HarnessNode, policy *lnrpc.RoutingPolicy,
746
        chanPoint *lnrpc.ChannelPoint, includeUnannounced bool) {
×
747

×
748
        require.NoError(
×
749
                h, hn.Watcher.WaitForChannelPolicyUpdate(
×
750
                        advertisingNode, policy,
×
751
                        chanPoint, includeUnannounced,
×
752
                ), "%s: error while waiting for channel update", hn.Name(),
×
753
        )
×
754
}
×
755

756
// WaitForGraphSync waits until the node is synced to graph or times out.
757
func (h *HarnessTest) WaitForGraphSync(hn *node.HarnessNode) {
×
758
        err := wait.NoError(func() error {
×
759
                resp := hn.RPC.GetInfo()
×
760
                if resp.SyncedToGraph {
×
761
                        return nil
×
762
                }
×
763

764
                return fmt.Errorf("node not synced to graph")
×
765
        }, DefaultTimeout)
766
        require.NoError(h, err, "%s: timeout while sync to graph", hn.Name())
×
767
}
768

769
// AssertNumUTXOsWithConf waits for the given number of UTXOs with the
770
// specified confirmations range to be available or fails if that isn't the
771
// case before the default timeout.
772
func (h *HarnessTest) AssertNumUTXOsWithConf(hn *node.HarnessNode,
773
        expectedUtxos int, max, min int32) []*lnrpc.Utxo {
×
774

×
775
        var unconfirmed bool
×
776

×
777
        if max == 0 {
×
778
                unconfirmed = true
×
779
        }
×
780

781
        var utxos []*lnrpc.Utxo
×
782
        err := wait.NoError(func() error {
×
783
                req := &walletrpc.ListUnspentRequest{
×
784
                        Account:         "",
×
785
                        MaxConfs:        max,
×
786
                        MinConfs:        min,
×
787
                        UnconfirmedOnly: unconfirmed,
×
788
                }
×
789
                resp := hn.RPC.ListUnspent(req)
×
790
                total := len(resp.Utxos)
×
791

×
792
                if total == expectedUtxos {
×
793
                        utxos = resp.Utxos
×
794

×
795
                        return nil
×
796
                }
×
797

798
                desc := "has UTXOs:\n"
×
799
                for _, utxo := range resp.Utxos {
×
800
                        desc += fmt.Sprintf("%v\n", utxo)
×
801
                }
×
802

803
                return fmt.Errorf("%s: assert num of UTXOs failed: want %d, "+
×
804
                        "got: %d, %s", hn.Name(), expectedUtxos, total, desc)
×
805
        }, DefaultTimeout)
806
        require.NoError(h, err, "timeout waiting for UTXOs")
×
807

×
808
        return utxos
×
809
}
810

811
// AssertNumUTXOsUnconfirmed asserts the expected num of unconfirmed utxos are
812
// seen.
813
func (h *HarnessTest) AssertNumUTXOsUnconfirmed(hn *node.HarnessNode,
814
        num int) []*lnrpc.Utxo {
×
815

×
816
        return h.AssertNumUTXOsWithConf(hn, num, 0, 0)
×
817
}
×
818

819
// AssertNumUTXOsConfirmed asserts the expected num of confirmed utxos are
820
// seen, which means the returned utxos have at least one confirmation.
821
func (h *HarnessTest) AssertNumUTXOsConfirmed(hn *node.HarnessNode,
822
        num int) []*lnrpc.Utxo {
×
823

×
824
        return h.AssertNumUTXOsWithConf(hn, num, math.MaxInt32, 1)
×
825
}
×
826

827
// AssertNumUTXOs asserts the expected num of utxos are seen, including
828
// confirmed and unconfirmed outputs.
829
func (h *HarnessTest) AssertNumUTXOs(hn *node.HarnessNode,
830
        num int) []*lnrpc.Utxo {
×
831

×
832
        return h.AssertNumUTXOsWithConf(hn, num, math.MaxInt32, 0)
×
833
}
×
834

835
// getUTXOs gets the number of newly created UTOXs within the current test
836
// scope.
837
func (h *HarnessTest) getUTXOs(hn *node.HarnessNode, account string,
838
        max, min int32) []*lnrpc.Utxo {
×
839

×
840
        var unconfirmed bool
×
841

×
842
        if max == 0 {
×
843
                unconfirmed = true
×
844
        }
×
845

846
        req := &walletrpc.ListUnspentRequest{
×
847
                Account:         account,
×
848
                MaxConfs:        max,
×
849
                MinConfs:        min,
×
850
                UnconfirmedOnly: unconfirmed,
×
851
        }
×
852
        resp := hn.RPC.ListUnspent(req)
×
853

×
854
        return resp.Utxos
×
855
}
856

857
// GetUTXOs returns all the UTXOs for the given node's account, including
858
// confirmed and unconfirmed.
859
func (h *HarnessTest) GetUTXOs(hn *node.HarnessNode,
860
        account string) []*lnrpc.Utxo {
×
861

×
862
        return h.getUTXOs(hn, account, math.MaxInt32, 0)
×
863
}
×
864

865
// GetUTXOsConfirmed returns the confirmed UTXOs for the given node's account.
866
func (h *HarnessTest) GetUTXOsConfirmed(hn *node.HarnessNode,
867
        account string) []*lnrpc.Utxo {
×
868

×
869
        return h.getUTXOs(hn, account, math.MaxInt32, 1)
×
870
}
×
871

872
// GetUTXOsUnconfirmed returns the unconfirmed UTXOs for the given node's
873
// account.
874
func (h *HarnessTest) GetUTXOsUnconfirmed(hn *node.HarnessNode,
875
        account string) []*lnrpc.Utxo {
×
876

×
877
        return h.getUTXOs(hn, account, 0, 0)
×
878
}
×
879

880
// WaitForBalanceConfirmed waits until the node sees the expected confirmed
881
// balance in its wallet.
882
func (h *HarnessTest) WaitForBalanceConfirmed(hn *node.HarnessNode,
883
        expected btcutil.Amount) {
×
884

×
885
        var lastBalance btcutil.Amount
×
886
        err := wait.NoError(func() error {
×
887
                resp := hn.RPC.WalletBalance()
×
888

×
889
                lastBalance = btcutil.Amount(resp.ConfirmedBalance)
×
890
                if lastBalance == expected {
×
891
                        return nil
×
892
                }
×
893

894
                return fmt.Errorf("expected %v, only have %v", expected,
×
895
                        lastBalance)
×
896
        }, DefaultTimeout)
897

898
        require.NoError(h, err, "timeout waiting for confirmed balances")
×
899
}
900

901
// WaitForBalanceUnconfirmed waits until the node sees the expected unconfirmed
902
// balance in its wallet.
903
func (h *HarnessTest) WaitForBalanceUnconfirmed(hn *node.HarnessNode,
904
        expected btcutil.Amount) {
×
905

×
906
        var lastBalance btcutil.Amount
×
907
        err := wait.NoError(func() error {
×
908
                resp := hn.RPC.WalletBalance()
×
909

×
910
                lastBalance = btcutil.Amount(resp.UnconfirmedBalance)
×
911
                if lastBalance == expected {
×
912
                        return nil
×
913
                }
×
914

915
                return fmt.Errorf("expected %v, only have %v", expected,
×
916
                        lastBalance)
×
917
        }, DefaultTimeout)
918

919
        require.NoError(h, err, "timeout waiting for unconfirmed balances")
×
920
}
921

922
// Random32Bytes generates a random 32 bytes which can be used as a pay hash,
923
// preimage, etc.
924
func (h *HarnessTest) Random32Bytes() []byte {
×
925
        randBuf := make([]byte, lntypes.HashSize)
×
926

×
927
        _, err := rand.Read(randBuf)
×
928
        require.NoErrorf(h, err, "internal error, cannot generate random bytes")
×
929

×
930
        return randBuf
×
931
}
×
932

933
// RandomPreimage generates a random preimage which can be used as a payment
934
// preimage.
935
func (h *HarnessTest) RandomPreimage() lntypes.Preimage {
×
936
        var preimage lntypes.Preimage
×
937
        copy(preimage[:], h.Random32Bytes())
×
938

×
939
        return preimage
×
940
}
×
941

942
// DecodeAddress decodes a given address and asserts there's no error.
943
func (h *HarnessTest) DecodeAddress(addr string) btcutil.Address {
×
944
        resp, err := btcutil.DecodeAddress(addr, miner.HarnessNetParams)
×
945
        require.NoError(h, err, "DecodeAddress failed")
×
946

×
947
        return resp
×
948
}
×
949

950
// PayToAddrScript creates a new script from the given address and asserts
951
// there's no error.
952
func (h *HarnessTest) PayToAddrScript(addr btcutil.Address) []byte {
×
953
        addrScript, err := txscript.PayToAddrScript(addr)
×
954
        require.NoError(h, err, "PayToAddrScript failed")
×
955

×
956
        return addrScript
×
957
}
×
958

959
// AssertChannelBalanceResp makes a ChannelBalance request and checks the
960
// returned response matches the expected.
961
func (h *HarnessTest) AssertChannelBalanceResp(hn *node.HarnessNode,
962
        expected *lnrpc.ChannelBalanceResponse) {
×
963

×
964
        resp := hn.RPC.ChannelBalance()
×
965

×
966
        // Ignore custom channel data of both expected and actual responses.
×
967
        expected.CustomChannelData = nil
×
968
        resp.CustomChannelData = nil
×
969

×
970
        require.True(h, proto.Equal(expected, resp), "balance is incorrect "+
×
971
                "got: %v, want: %v", resp, expected)
×
972
}
×
973

974
// GetChannelByChanPoint tries to find a channel matching the channel point and
975
// asserts. It returns the channel found.
976
func (h *HarnessTest) GetChannelByChanPoint(hn *node.HarnessNode,
977
        chanPoint *lnrpc.ChannelPoint) *lnrpc.Channel {
×
978

×
979
        channel, err := h.findChannel(hn, chanPoint)
×
980
        require.NoErrorf(h, err, "channel not found using %v", chanPoint)
×
981

×
982
        return channel
×
983
}
×
984

985
// GetChannelCommitType retrieves the active channel commitment type for the
986
// given chan point.
987
func (h *HarnessTest) GetChannelCommitType(hn *node.HarnessNode,
988
        chanPoint *lnrpc.ChannelPoint) lnrpc.CommitmentType {
×
989

×
990
        c := h.GetChannelByChanPoint(hn, chanPoint)
×
991

×
992
        return c.CommitmentType
×
993
}
×
994

995
// AssertNumPendingOpenChannels asserts that a given node have the expected
996
// number of pending open channels.
997
func (h *HarnessTest) AssertNumPendingOpenChannels(hn *node.HarnessNode,
998
        expected int) []*lnrpc.PendingChannelsResponse_PendingOpenChannel {
×
999

×
1000
        var channels []*lnrpc.PendingChannelsResponse_PendingOpenChannel
×
1001

×
1002
        oldNum := hn.State.OpenChannel.Pending
×
1003

×
1004
        err := wait.NoError(func() error {
×
1005
                resp := hn.RPC.PendingChannels()
×
1006
                channels = resp.PendingOpenChannels
×
1007
                total := len(channels)
×
1008

×
1009
                numChans := total - oldNum
×
1010

×
1011
                if numChans != expected {
×
1012
                        return errNumNotMatched(hn.Name(),
×
1013
                                "pending open channels", expected,
×
1014
                                numChans, total, oldNum)
×
1015
                }
×
1016

1017
                return nil
×
1018
        }, DefaultTimeout)
1019

1020
        require.NoError(h, err, "num of pending open channels not match")
×
1021

×
1022
        return channels
×
1023
}
1024

1025
// AssertNodesNumPendingOpenChannels asserts that both of the nodes have the
1026
// expected number of pending open channels.
1027
func (h *HarnessTest) AssertNodesNumPendingOpenChannels(a, b *node.HarnessNode,
1028
        expected int) {
×
1029

×
1030
        h.AssertNumPendingOpenChannels(a, expected)
×
1031
        h.AssertNumPendingOpenChannels(b, expected)
×
1032
}
×
1033

1034
// AssertPaymentStatusFromStream takes a client stream and asserts the payment
1035
// is in desired status before default timeout. The payment found is returned
1036
// once succeeded.
1037
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
1038
        status lnrpc.Payment_PaymentStatus) *lnrpc.Payment {
×
1039

×
1040
        return h.assertPaymentStatusWithTimeout(
×
1041
                stream, status, wait.PaymentTimeout,
×
1042
        )
×
1043
}
×
1044

1045
// AssertPaymentSucceedWithTimeout asserts that a payment is succeeded within
1046
// the specified timeout.
1047
func (h *HarnessTest) AssertPaymentSucceedWithTimeout(stream rpc.PaymentClient,
1048
        timeout time.Duration) *lnrpc.Payment {
×
1049

×
1050
        return h.assertPaymentStatusWithTimeout(
×
1051
                stream, lnrpc.Payment_SUCCEEDED, timeout,
×
1052
        )
×
1053
}
×
1054

1055
// assertPaymentStatusWithTimeout takes a client stream and asserts the payment
1056
// is in desired status before the specified timeout. The payment found is
1057
// returned once succeeded.
1058
func (h *HarnessTest) assertPaymentStatusWithTimeout(stream rpc.PaymentClient,
1059
        status lnrpc.Payment_PaymentStatus,
1060
        timeout time.Duration) *lnrpc.Payment {
×
1061

×
1062
        var target *lnrpc.Payment
×
1063
        err := wait.NoError(func() error {
×
1064
                // Consume one message. This will raise an error if the message
×
1065
                // is not received within DefaultTimeout.
×
1066
                payment, err := h.receivePaymentUpdateWithTimeout(
×
1067
                        stream, timeout,
×
1068
                )
×
1069
                if err != nil {
×
1070
                        return fmt.Errorf("received error from payment "+
×
1071
                                "stream: %s", err)
×
1072
                }
×
1073

1074
                // Return if the desired payment state is reached.
1075
                if payment.Status == status {
×
1076
                        target = payment
×
1077

×
1078
                        return nil
×
1079
                }
×
1080

1081
                // Return the err so that it can be used for debugging when
1082
                // timeout is reached.
1083
                return fmt.Errorf("payment %v status, got %v, want %v",
×
1084
                        payment.PaymentHash, payment.Status, status)
×
1085
        }, timeout)
1086

1087
        require.NoError(h, err, "timeout while waiting payment")
×
1088

×
1089
        return target
×
1090
}
1091

1092
// ReceivePaymentUpdate waits until a message is received on the payment client
1093
// stream or the timeout is reached.
1094
func (h *HarnessTest) ReceivePaymentUpdate(
1095
        stream rpc.PaymentClient) (*lnrpc.Payment, error) {
×
1096

×
1097
        return h.receivePaymentUpdateWithTimeout(stream, DefaultTimeout)
×
1098
}
×
1099

1100
// receivePaymentUpdateWithTimeout waits until a message is received on the
1101
// payment client stream or the timeout is reached.
1102
func (h *HarnessTest) receivePaymentUpdateWithTimeout(stream rpc.PaymentClient,
1103
        timeout time.Duration) (*lnrpc.Payment, error) {
×
1104

×
1105
        chanMsg := make(chan *lnrpc.Payment, 1)
×
1106
        errChan := make(chan error, 1)
×
1107

×
1108
        go func() {
×
1109
                // Consume one message. This will block until the message is
×
1110
                // received.
×
1111
                resp, err := stream.Recv()
×
1112
                if err != nil {
×
1113
                        errChan <- err
×
1114

×
1115
                        return
×
1116
                }
×
1117
                chanMsg <- resp
×
1118
        }()
1119

1120
        select {
×
1121
        case <-time.After(timeout):
×
1122
                require.Fail(h, "timeout", "timeout waiting for payment update")
×
1123
                return nil, nil
×
1124

1125
        case err := <-errChan:
×
1126
                return nil, err
×
1127

1128
        case updateMsg := <-chanMsg:
×
1129
                return updateMsg, nil
×
1130
        }
1131
}
1132

1133
// AssertInvoiceSettled asserts a given invoice specified by its payment
1134
// address is settled.
1135
func (h *HarnessTest) AssertInvoiceSettled(hn *node.HarnessNode, addr []byte) {
×
1136
        msg := &invoicesrpc.LookupInvoiceMsg{
×
1137
                InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
×
1138
                        PaymentAddr: addr,
×
1139
                },
×
1140
        }
×
1141

×
1142
        err := wait.NoError(func() error {
×
1143
                invoice := hn.RPC.LookupInvoiceV2(msg)
×
1144
                if invoice.State == lnrpc.Invoice_SETTLED {
×
1145
                        return nil
×
1146
                }
×
1147

1148
                return fmt.Errorf("%s: invoice with payment address %x not "+
×
1149
                        "settled", hn.Name(), addr)
×
1150
        }, DefaultTimeout)
1151
        require.NoError(h, err, "timeout waiting for invoice settled state")
×
1152
}
1153

1154
// AssertNodeNumChannels polls the provided node's list channels rpc until it
1155
// reaches the desired number of total channels.
1156
func (h *HarnessTest) AssertNodeNumChannels(hn *node.HarnessNode,
1157
        numChannels int) {
×
1158

×
1159
        // Get the total number of channels.
×
1160
        old := hn.State.OpenChannel.Active + hn.State.OpenChannel.Inactive
×
1161

×
1162
        err := wait.NoError(func() error {
×
1163
                // We require the RPC call to be succeeded and won't wait for
×
1164
                // it as it's an unexpected behavior.
×
1165
                chanInfo := hn.RPC.ListChannels(&lnrpc.ListChannelsRequest{})
×
1166

×
1167
                // Return true if the query returned the expected number of
×
1168
                // channels.
×
1169
                num := len(chanInfo.Channels) - old
×
1170
                if num != numChannels {
×
1171
                        return fmt.Errorf("expected %v channels, got %v",
×
1172
                                numChannels, num)
×
1173
                }
×
1174

1175
                return nil
×
1176
        }, DefaultTimeout)
1177

1178
        require.NoError(h, err, "timeout checking node's num of channels")
×
1179
}
1180

1181
// AssertChannelLocalBalance checks the local balance of the given channel is
1182
// expected. The channel found using the specified channel point is returned.
1183
func (h *HarnessTest) AssertChannelLocalBalance(hn *node.HarnessNode,
1184
        cp *lnrpc.ChannelPoint, balance int64) *lnrpc.Channel {
×
1185

×
1186
        var result *lnrpc.Channel
×
1187

×
1188
        // Get the funding point.
×
1189
        err := wait.NoError(func() error {
×
1190
                // Find the target channel first.
×
1191
                target, err := h.findChannel(hn, cp)
×
1192

×
1193
                // Exit early if the channel is not found.
×
1194
                if err != nil {
×
1195
                        return fmt.Errorf("check balance failed: %w", err)
×
1196
                }
×
1197

1198
                result = target
×
1199

×
1200
                // Check local balance.
×
1201
                if target.LocalBalance == balance {
×
1202
                        return nil
×
1203
                }
×
1204

1205
                return fmt.Errorf("balance is incorrect, got %v, expected %v",
×
1206
                        target.LocalBalance, balance)
×
1207
        }, DefaultTimeout)
1208

1209
        require.NoError(h, err, "timeout while checking for balance")
×
1210

×
1211
        return result
×
1212
}
1213

1214
// AssertChannelNumUpdates checks the num of updates is expected from the given
1215
// channel.
1216
func (h *HarnessTest) AssertChannelNumUpdates(hn *node.HarnessNode,
1217
        num uint64, cp *lnrpc.ChannelPoint) {
×
1218

×
1219
        old := int(hn.State.OpenChannel.NumUpdates)
×
1220

×
1221
        // Find the target channel first.
×
1222
        target, err := h.findChannel(hn, cp)
×
1223
        require.NoError(h, err, "unable to find channel")
×
1224

×
1225
        err = wait.NoError(func() error {
×
1226
                total := int(target.NumUpdates)
×
1227
                if total-old == int(num) {
×
1228
                        return nil
×
1229
                }
×
1230

1231
                return errNumNotMatched(hn.Name(), "channel updates",
×
1232
                        int(num), total-old, total, old)
×
1233
        }, DefaultTimeout)
1234
        require.NoError(h, err, "timeout while checking for num of updates")
×
1235
}
1236

1237
// AssertNumActiveHtlcs asserts that a given number of HTLCs are seen in the
1238
// node's channels.
1239
func (h *HarnessTest) AssertNumActiveHtlcs(hn *node.HarnessNode, num int) {
×
1240
        old := hn.State.HTLC
×
1241

×
1242
        err := wait.NoError(func() error {
×
1243
                // pendingHTLCs is used to print unacked HTLCs, if found.
×
1244
                var pendingHTLCs []string
×
1245

×
1246
                // We require the RPC call to be succeeded and won't wait for
×
1247
                // it as it's an unexpected behavior.
×
1248
                req := &lnrpc.ListChannelsRequest{}
×
1249
                nodeChans := hn.RPC.ListChannels(req)
×
1250

×
1251
                total := 0
×
1252
                for _, channel := range nodeChans.Channels {
×
1253
                        for _, htlc := range channel.PendingHtlcs {
×
1254
                                if htlc.LockedIn {
×
1255
                                        total++
×
1256
                                }
×
1257

1258
                                rHash := fmt.Sprintf("%x", htlc.HashLock)
×
1259
                                pendingHTLCs = append(pendingHTLCs, rHash)
×
1260
                        }
1261
                }
1262
                if total-old != num {
×
1263
                        desc := fmt.Sprintf("active HTLCs: unacked HTLCs: %v",
×
1264
                                pendingHTLCs)
×
1265

×
1266
                        return errNumNotMatched(hn.Name(), desc,
×
1267
                                num, total-old, total, old)
×
1268
                }
×
1269

1270
                return nil
×
1271
        }, DefaultTimeout)
1272

1273
        require.NoErrorf(h, err, "%s timeout checking num active htlcs",
×
1274
                hn.Name())
×
1275
}
1276

1277
// AssertIncomingHTLCActive asserts the node has a pending incoming HTLC in the
1278
// given channel. Returns the HTLC if found and active.
1279
func (h *HarnessTest) AssertIncomingHTLCActive(hn *node.HarnessNode,
1280
        cp *lnrpc.ChannelPoint, payHash []byte) *lnrpc.HTLC {
×
1281

×
1282
        return h.assertHTLCActive(hn, cp, payHash, true)
×
1283
}
×
1284

1285
// AssertOutgoingHTLCActive asserts the node has a pending outgoing HTLC in the
1286
// given channel. Returns the HTLC if found and active.
1287
func (h *HarnessTest) AssertOutgoingHTLCActive(hn *node.HarnessNode,
1288
        cp *lnrpc.ChannelPoint, payHash []byte) *lnrpc.HTLC {
×
1289

×
1290
        return h.assertHTLCActive(hn, cp, payHash, false)
×
1291
}
×
1292

1293
// assertHLTCActive asserts the node has a pending HTLC in the given channel.
1294
// Returns the HTLC if found and active.
1295
func (h *HarnessTest) assertHTLCActive(hn *node.HarnessNode,
1296
        cp *lnrpc.ChannelPoint, payHash []byte, incoming bool) *lnrpc.HTLC {
×
1297

×
1298
        var result *lnrpc.HTLC
×
1299
        target := hex.EncodeToString(payHash)
×
1300

×
1301
        err := wait.NoError(func() error {
×
1302
                // We require the RPC call to be succeeded and won't wait for
×
1303
                // it as it's an unexpected behavior.
×
1304
                ch := h.GetChannelByChanPoint(hn, cp)
×
1305

×
1306
                // Check all payment hashes active for this channel.
×
1307
                for _, htlc := range ch.PendingHtlcs {
×
1308
                        rHash := hex.EncodeToString(htlc.HashLock)
×
1309
                        if rHash != target {
×
1310
                                continue
×
1311
                        }
1312

1313
                        // If the payment hash is found, check the incoming
1314
                        // field.
1315
                        if htlc.Incoming == incoming {
×
1316
                                // Return the result if it's locked in.
×
1317
                                if htlc.LockedIn {
×
1318
                                        result = htlc
×
1319
                                        return nil
×
1320
                                }
×
1321

1322
                                return fmt.Errorf("htlc(%x) not locked in",
×
1323
                                        payHash)
×
1324
                        }
1325

1326
                        // Otherwise we do have the HTLC but its direction is
1327
                        // not right.
1328
                        have, want := "outgoing", "incoming"
×
1329
                        if htlc.Incoming {
×
1330
                                have, want = "incoming", "outgoing"
×
1331
                        }
×
1332

1333
                        return fmt.Errorf("htlc(%x) has wrong direction - "+
×
1334
                                "want: %s, have: %s", payHash, want, have)
×
1335
                }
1336

1337
                return fmt.Errorf("htlc not found using payHash %x", payHash)
×
1338
        }, DefaultTimeout)
1339
        require.NoError(h, err, "%s: timeout checking pending HTLC", hn.Name())
×
1340

×
1341
        return result
×
1342
}
1343

1344
// AssertHLTCNotActive asserts the node doesn't have a pending HTLC in the
1345
// given channel, which mean either the HTLC never exists, or it was pending
1346
// and now settled. Returns the HTLC if found and active.
1347
//
1348
// NOTE: to check a pending HTLC becoming settled, first use AssertHLTCActive
1349
// then follow this check.
1350
func (h *HarnessTest) AssertHTLCNotActive(hn *node.HarnessNode,
1351
        cp *lnrpc.ChannelPoint, payHash []byte) *lnrpc.HTLC {
×
1352

×
1353
        var result *lnrpc.HTLC
×
1354
        target := hex.EncodeToString(payHash)
×
1355

×
1356
        err := wait.NoError(func() error {
×
1357
                // We require the RPC call to be succeeded and won't wait for
×
1358
                // it as it's an unexpected behavior.
×
1359
                ch := h.GetChannelByChanPoint(hn, cp)
×
1360

×
1361
                // Check all payment hashes active for this channel.
×
1362
                for _, htlc := range ch.PendingHtlcs {
×
1363
                        h := hex.EncodeToString(htlc.HashLock)
×
1364

×
1365
                        // Break if found the htlc.
×
1366
                        if h == target {
×
1367
                                result = htlc
×
1368
                                break
×
1369
                        }
1370
                }
1371

1372
                // If we've found nothing, we're done.
1373
                if result == nil {
×
1374
                        return nil
×
1375
                }
×
1376

1377
                // Otherwise return an error.
1378
                return fmt.Errorf("node [%s:%x] still has: the payHash %x",
×
1379
                        hn.Name(), hn.PubKey[:], payHash)
×
1380
        }, DefaultTimeout)
1381
        require.NoError(h, err, "timeout checking pending HTLC")
×
1382

×
1383
        return result
×
1384
}
1385

1386
// ReceiveSingleInvoice waits until a message is received on the subscribe
1387
// single invoice stream or the timeout is reached.
1388
func (h *HarnessTest) ReceiveSingleInvoice(
1389
        stream rpc.SingleInvoiceClient) *lnrpc.Invoice {
×
1390

×
1391
        chanMsg := make(chan *lnrpc.Invoice, 1)
×
1392
        errChan := make(chan error, 1)
×
1393
        go func() {
×
1394
                // Consume one message. This will block until the message is
×
1395
                // received.
×
1396
                resp, err := stream.Recv()
×
1397
                if err != nil {
×
1398
                        errChan <- err
×
1399

×
1400
                        return
×
1401
                }
×
1402
                chanMsg <- resp
×
1403
        }()
1404

1405
        select {
×
1406
        case <-time.After(DefaultTimeout):
×
1407
                require.Fail(h, "timeout", "timeout receiving single invoice")
×
1408

1409
        case err := <-errChan:
×
1410
                require.Failf(h, "err from stream",
×
1411
                        "received err from stream: %v", err)
×
1412

1413
        case updateMsg := <-chanMsg:
×
1414
                return updateMsg
×
1415
        }
1416

1417
        return nil
×
1418
}
1419

1420
// AssertInvoiceState takes a single invoice subscription stream and asserts
1421
// that a given invoice has became the desired state before timeout and returns
1422
// the invoice found.
1423
func (h *HarnessTest) AssertInvoiceState(stream rpc.SingleInvoiceClient,
1424
        state lnrpc.Invoice_InvoiceState) *lnrpc.Invoice {
×
1425

×
1426
        var invoice *lnrpc.Invoice
×
1427

×
1428
        err := wait.NoError(func() error {
×
1429
                invoice = h.ReceiveSingleInvoice(stream)
×
1430
                if invoice.State == state {
×
1431
                        return nil
×
1432
                }
×
1433

1434
                return fmt.Errorf("mismatched invoice state, want %v, got %v",
×
1435
                        state, invoice.State)
×
1436
        }, DefaultTimeout)
1437
        require.NoError(h, err, "timeout waiting for invoice state: %v", state)
×
1438

×
1439
        return invoice
×
1440
}
1441

1442
// assertAllTxesSpendFrom asserts that all txes in the list spend from the
1443
// given tx.
1444
func (h *HarnessTest) AssertAllTxesSpendFrom(txes []*wire.MsgTx,
1445
        prevTxid chainhash.Hash) {
×
1446

×
1447
        for _, tx := range txes {
×
1448
                if tx.TxIn[0].PreviousOutPoint.Hash != prevTxid {
×
1449
                        require.Failf(h, "", "tx %v did not spend from %v",
×
1450
                                tx.TxHash(), prevTxid)
×
1451
                }
×
1452
        }
1453
}
1454

1455
// AssertTxSpendFrom asserts that a given tx is spent from a previous tx.
1456
func (h *HarnessTest) AssertTxSpendFrom(tx *wire.MsgTx,
1457
        prevTxid chainhash.Hash) {
×
1458

×
1459
        if tx.TxIn[0].PreviousOutPoint.Hash != prevTxid {
×
1460
                require.Failf(h, "", "tx %v did not spend from %v",
×
1461
                        tx.TxHash(), prevTxid)
×
1462
        }
×
1463
}
1464

1465
type PendingForceClose *lnrpc.PendingChannelsResponse_ForceClosedChannel
1466

1467
// AssertChannelPendingForceClose asserts that the given channel found in the
1468
// node is pending force close. Returns the PendingForceClose if found.
1469
func (h *HarnessTest) AssertChannelPendingForceClose(hn *node.HarnessNode,
1470
        chanPoint *lnrpc.ChannelPoint) PendingForceClose {
×
1471

×
1472
        var target PendingForceClose
×
1473

×
1474
        op := h.OutPointFromChannelPoint(chanPoint)
×
1475

×
1476
        err := wait.NoError(func() error {
×
1477
                resp := hn.RPC.PendingChannels()
×
1478

×
1479
                forceCloseChans := resp.PendingForceClosingChannels
×
1480
                for _, ch := range forceCloseChans {
×
1481
                        if ch.Channel.ChannelPoint == op.String() {
×
1482
                                target = ch
×
1483

×
1484
                                return nil
×
1485
                        }
×
1486
                }
1487

1488
                return fmt.Errorf("%v: channel %s not found in pending "+
×
1489
                        "force close", hn.Name(), chanPoint)
×
1490
        }, DefaultTimeout)
1491
        require.NoError(h, err, "assert pending force close timed out")
×
1492

×
1493
        return target
×
1494
}
1495

1496
// AssertNumHTLCsAndStage takes a pending force close channel's channel point
1497
// and asserts the expected number of pending HTLCs and HTLC stage are matched.
1498
func (h *HarnessTest) AssertNumHTLCsAndStage(hn *node.HarnessNode,
1499
        chanPoint *lnrpc.ChannelPoint, num int, stage uint32) {
×
1500

×
1501
        // Get the channel output point.
×
1502
        cp := h.OutPointFromChannelPoint(chanPoint)
×
1503

×
1504
        var target PendingForceClose
×
1505
        checkStage := func() error {
×
1506
                resp := hn.RPC.PendingChannels()
×
1507
                if len(resp.PendingForceClosingChannels) == 0 {
×
1508
                        return fmt.Errorf("zero pending force closing channels")
×
1509
                }
×
1510

1511
                for _, ch := range resp.PendingForceClosingChannels {
×
1512
                        if ch.Channel.ChannelPoint == cp.String() {
×
1513
                                target = ch
×
1514

×
1515
                                break
×
1516
                        }
1517
                }
1518

1519
                if target == nil {
×
1520
                        return fmt.Errorf("cannot find pending force closing "+
×
1521
                                "channel using %v", cp)
×
1522
                }
×
1523

1524
                if target.LimboBalance == 0 {
×
1525
                        return fmt.Errorf("zero limbo balance")
×
1526
                }
×
1527

1528
                if len(target.PendingHtlcs) != num {
×
1529
                        return fmt.Errorf("got %d pending htlcs, want %d, %s",
×
1530
                                len(target.PendingHtlcs), num,
×
1531
                                lnutils.SpewLogClosure(target.PendingHtlcs)())
×
1532
                }
×
1533

1534
                for _, htlc := range target.PendingHtlcs {
×
1535
                        if htlc.Stage == stage {
×
1536
                                continue
×
1537
                        }
1538

1539
                        return fmt.Errorf("HTLC %s got stage: %v, "+
×
1540
                                "want stage: %v", htlc.Outpoint, htlc.Stage,
×
1541
                                stage)
×
1542
                }
1543

1544
                return nil
×
1545
        }
1546

1547
        require.NoErrorf(h, wait.NoError(checkStage, DefaultTimeout),
×
1548
                "timeout waiting for htlc stage")
×
1549
}
1550

1551
// findPayment queries the payment from the node's ListPayments which matches
1552
// the specified preimage hash.
1553
func (h *HarnessTest) findPayment(hn *node.HarnessNode,
1554
        paymentHash string) (*lnrpc.Payment, error) {
×
1555

×
1556
        req := &lnrpc.ListPaymentsRequest{IncludeIncomplete: true}
×
1557
        paymentsResp := hn.RPC.ListPayments(req)
×
1558

×
1559
        for _, p := range paymentsResp.Payments {
×
1560
                if p.PaymentHash == paymentHash {
×
1561
                        return p, nil
×
1562
                }
×
1563
        }
1564

1565
        return nil, fmt.Errorf("payment %v cannot be found", paymentHash)
×
1566
}
1567

1568
// PaymentCheck is a function that checks a payment for a specific condition.
1569
type PaymentCheck func(*lnrpc.Payment) error
1570

1571
// AssertPaymentStatus asserts that the given node list a payment with the given
1572
// payment hash has the expected status. It also checks that the payment has the
1573
// expected preimage, which is empty when it's not settled and matches the given
1574
// preimage when it's succeeded.
1575
func (h *HarnessTest) AssertPaymentStatus(hn *node.HarnessNode,
1576
        payHash lntypes.Hash, status lnrpc.Payment_PaymentStatus,
1577
        checks ...PaymentCheck) *lnrpc.Payment {
×
1578

×
1579
        var target *lnrpc.Payment
×
1580

×
1581
        err := wait.NoError(func() error {
×
1582
                p, err := h.findPayment(hn, payHash.String())
×
1583
                if err != nil {
×
1584
                        return err
×
1585
                }
×
1586

1587
                if status == p.Status {
×
1588
                        target = p
×
1589
                        return nil
×
1590
                }
×
1591

1592
                return fmt.Errorf("payment: %v status not match, want %s "+
×
1593
                        "got %s", payHash, status, p.Status)
×
1594
        }, DefaultTimeout)
1595
        require.NoError(h, err, "timeout checking payment status")
×
1596

×
1597
        switch status {
×
1598
        // If this expected status is SUCCEEDED, we expect the final
1599
        // preimage.
1600
        case lnrpc.Payment_SUCCEEDED:
×
1601
                preimage, err := lntypes.MakePreimageFromStr(
×
1602
                        target.PaymentPreimage,
×
1603
                )
×
1604
                require.NoError(h, err, "fail to make preimage")
×
1605
                require.Equal(h, payHash, preimage.Hash(), "preimage not match")
×
1606

1607
        // Otherwise we expect an all-zero preimage.
1608
        default:
×
1609
                require.Equal(h, (lntypes.Preimage{}).String(),
×
1610
                        target.PaymentPreimage, "expected zero preimage")
×
1611
        }
1612

1613
        // Perform any additional checks on the payment.
1614
        for _, check := range checks {
×
1615
                require.NoError(h, check(target))
×
1616
        }
×
1617

1618
        return target
×
1619
}
1620

1621
// AssertPaymentFailureReason asserts that the given node lists a payment with
1622
// the given preimage which has the expected failure reason.
1623
func (h *HarnessTest) AssertPaymentFailureReason(
1624
        hn *node.HarnessNode, preimage lntypes.Preimage,
1625
        reason lnrpc.PaymentFailureReason) *lnrpc.Payment {
×
1626

×
1627
        var payment *lnrpc.Payment
×
1628

×
1629
        payHash := preimage.Hash()
×
1630
        err := wait.NoError(func() error {
×
1631
                p, err := h.findPayment(hn, payHash.String())
×
1632
                if err != nil {
×
1633
                        return err
×
1634
                }
×
1635

1636
                payment = p
×
1637

×
1638
                if reason == p.FailureReason {
×
1639
                        return nil
×
1640
                }
×
1641

1642
                return fmt.Errorf("payment: %v failure reason not match, "+
×
1643
                        "want %s(%d) got %s(%d)", payHash, reason, reason,
×
1644
                        p.FailureReason, p.FailureReason)
×
1645
        }, DefaultTimeout)
1646
        require.NoError(h, err, "timeout checking payment failure reason")
×
1647

×
1648
        return payment
×
1649
}
1650

1651
// AssertActiveNodesSynced asserts all active nodes have synced to the chain.
1652
func (h *HarnessTest) AssertActiveNodesSynced() {
×
1653
        for _, node := range h.manager.activeNodes {
×
1654
                h.WaitForBlockchainSync(node)
×
1655
        }
×
1656
}
1657

1658
// AssertActiveNodesSyncedTo asserts all active nodes have synced to the
1659
// provided bestBlock.
1660
func (h *HarnessTest) AssertActiveNodesSyncedTo(bestBlock chainhash.Hash) {
×
1661
        for _, node := range h.manager.activeNodes {
×
1662
                h.WaitForBlockchainSyncTo(node, bestBlock)
×
1663
        }
×
1664
}
1665

1666
// AssertPeerNotConnected asserts that the given node b is not connected to a.
1667
func (h *HarnessTest) AssertPeerNotConnected(a, b *node.HarnessNode) {
×
1668
        err := wait.NoError(func() error {
×
1669
                // We require the RPC call to be succeeded and won't wait for
×
1670
                // it as it's an unexpected behavior.
×
1671
                resp := a.RPC.ListPeers()
×
1672

×
1673
                // If node B is seen in the ListPeers response from node A,
×
1674
                // then we return false as the connection has been fully
×
1675
                // established.
×
1676
                for _, peer := range resp.Peers {
×
1677
                        if peer.PubKey == b.PubKeyStr {
×
1678
                                return fmt.Errorf("peers %s and %s still "+
×
1679
                                        "connected", a.Name(), b.Name())
×
1680
                        }
×
1681
                }
1682

1683
                return nil
×
1684
        }, DefaultTimeout)
1685
        require.NoError(h, err, "timeout checking peers not connected")
×
1686
}
1687

1688
// AssertNotConnected asserts that two peers are not connected.
1689
func (h *HarnessTest) AssertNotConnected(a, b *node.HarnessNode) {
×
NEW
1690
        // Sleep one second before the assertion to make sure that when there's
×
NEW
1691
        // a RPC call to connect, that RPC call is finished before the
×
NEW
1692
        // assertion.
×
NEW
1693
        time.Sleep(1 * time.Second)
×
NEW
1694

×
1695
        h.AssertPeerNotConnected(a, b)
×
1696
        h.AssertPeerNotConnected(b, a)
×
1697
}
×
1698

1699
// AssertConnected asserts that two peers are connected.
1700
func (h *HarnessTest) AssertConnected(a, b *node.HarnessNode) {
×
1701
        h.AssertPeerConnected(a, b)
×
1702
        h.AssertPeerConnected(b, a)
×
1703
}
×
1704

1705
// AssertAmountPaid checks that the ListChannels command of the provided
1706
// node list the total amount sent and received as expected for the
1707
// provided channel.
1708
func (h *HarnessTest) AssertAmountPaid(channelName string, hn *node.HarnessNode,
1709
        chanPoint *lnrpc.ChannelPoint, amountSent, amountReceived int64) {
×
1710

×
1711
        checkAmountPaid := func() error {
×
1712
                // Find the targeted channel.
×
1713
                channel, err := h.findChannel(hn, chanPoint)
×
1714
                if err != nil {
×
1715
                        return fmt.Errorf("assert amount failed: %w", err)
×
1716
                }
×
1717

1718
                if channel.TotalSatoshisSent != amountSent {
×
1719
                        return fmt.Errorf("%v: incorrect amount"+
×
1720
                                " sent: %v != %v", channelName,
×
1721
                                channel.TotalSatoshisSent,
×
1722
                                amountSent)
×
1723
                }
×
1724
                if channel.TotalSatoshisReceived !=
×
1725
                        amountReceived {
×
1726

×
1727
                        return fmt.Errorf("%v: incorrect amount"+
×
1728
                                " received: %v != %v",
×
1729
                                channelName,
×
1730
                                channel.TotalSatoshisReceived,
×
1731
                                amountReceived)
×
1732
                }
×
1733

1734
                return nil
×
1735
        }
1736

1737
        // As far as HTLC inclusion in commitment transaction might be
1738
        // postponed we will try to check the balance couple of times,
1739
        // and then if after some period of time we receive wrong
1740
        // balance return the error.
1741
        err := wait.NoError(checkAmountPaid, DefaultTimeout)
×
1742
        require.NoError(h, err, "timeout while checking amount paid")
×
1743
}
1744

1745
// AssertLastHTLCError checks that the last sent HTLC of the last payment sent
1746
// by the given node failed with the expected failure code.
1747
func (h *HarnessTest) AssertLastHTLCError(hn *node.HarnessNode,
1748
        code lnrpc.Failure_FailureCode) {
×
1749

×
1750
        // Use -1 to specify the last HTLC.
×
1751
        h.assertHTLCError(hn, code, -1)
×
1752
}
×
1753

1754
// AssertFirstHTLCError checks that the first HTLC of the last payment sent
1755
// by the given node failed with the expected failure code.
1756
func (h *HarnessTest) AssertFirstHTLCError(hn *node.HarnessNode,
1757
        code lnrpc.Failure_FailureCode) {
×
1758

×
1759
        // Use 0 to specify the first HTLC.
×
1760
        h.assertHTLCError(hn, code, 0)
×
1761
}
×
1762

1763
// assertLastHTLCError checks that the HTLC at the specified index of the last
1764
// payment sent by the given node failed with the expected failure code.
1765
func (h *HarnessTest) assertHTLCError(hn *node.HarnessNode,
1766
        code lnrpc.Failure_FailureCode, index int) {
×
1767

×
1768
        req := &lnrpc.ListPaymentsRequest{
×
1769
                IncludeIncomplete: true,
×
1770
        }
×
1771

×
1772
        err := wait.NoError(func() error {
×
1773
                paymentsResp := hn.RPC.ListPayments(req)
×
1774

×
1775
                payments := paymentsResp.Payments
×
1776
                if len(payments) == 0 {
×
1777
                        return fmt.Errorf("no payments found")
×
1778
                }
×
1779

1780
                payment := payments[len(payments)-1]
×
1781
                htlcs := payment.Htlcs
×
1782
                if len(htlcs) == 0 {
×
1783
                        return fmt.Errorf("no htlcs found")
×
1784
                }
×
1785

1786
                // If the index is greater than 0, check we have enough htlcs.
1787
                if index > 0 && len(htlcs) <= index {
×
1788
                        return fmt.Errorf("not enough htlcs")
×
1789
                }
×
1790

1791
                // If index is less than or equal to 0, we will read the last
1792
                // htlc.
1793
                if index <= 0 {
×
1794
                        index = len(htlcs) - 1
×
1795
                }
×
1796

1797
                htlc := htlcs[index]
×
1798

×
1799
                // The htlc must have a status of failed.
×
1800
                if htlc.Status != lnrpc.HTLCAttempt_FAILED {
×
1801
                        return fmt.Errorf("htlc should be failed")
×
1802
                }
×
1803
                // The failure field must not be empty.
1804
                if htlc.Failure == nil {
×
1805
                        return fmt.Errorf("expected htlc failure")
×
1806
                }
×
1807

1808
                // Exit if the expected code is found.
1809
                if htlc.Failure.Code == code {
×
1810
                        return nil
×
1811
                }
×
1812

1813
                return fmt.Errorf("unexpected failure code")
×
1814
        }, DefaultTimeout)
1815

1816
        require.NoError(h, err, "timeout checking HTLC error")
×
1817
}
1818

1819
// AssertZombieChannel asserts that a given channel found using the chanID is
1820
// marked as zombie.
1821
func (h *HarnessTest) AssertZombieChannel(hn *node.HarnessNode, chanID uint64) {
×
1822
        ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
×
1823
        defer cancel()
×
1824

×
1825
        err := wait.NoError(func() error {
×
1826
                _, err := hn.RPC.LN.GetChanInfo(
×
1827
                        ctxt, &lnrpc.ChanInfoRequest{ChanId: chanID},
×
1828
                )
×
1829
                if err == nil {
×
1830
                        return fmt.Errorf("expected error but got nil")
×
1831
                }
×
1832

1833
                if !strings.Contains(err.Error(), "marked as zombie") {
×
1834
                        return fmt.Errorf("expected error to contain '%s' but "+
×
1835
                                "was '%v'", "marked as zombie", err)
×
1836
                }
×
1837

1838
                return nil
×
1839
        }, DefaultTimeout)
1840
        require.NoError(h, err, "timeout while checking zombie channel")
×
1841
}
1842

1843
// AssertNotInGraph asserts that a given channel is either not found at all in
1844
// the graph or that it has been marked as a zombie.
1845
func (h *HarnessTest) AssertNotInGraph(hn *node.HarnessNode, chanID uint64) {
×
1846
        ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
×
1847
        defer cancel()
×
1848

×
1849
        err := wait.NoError(func() error {
×
1850
                _, err := hn.RPC.LN.GetChanInfo(
×
1851
                        ctxt, &lnrpc.ChanInfoRequest{ChanId: chanID},
×
1852
                )
×
1853
                if err == nil {
×
1854
                        return fmt.Errorf("expected error but got nil")
×
1855
                }
×
1856

1857
                switch {
×
1858
                case strings.Contains(err.Error(), "marked as zombie"):
×
1859
                        return nil
×
1860

1861
                case strings.Contains(err.Error(), "edge not found"):
×
1862
                        return nil
×
1863

1864
                default:
×
1865
                        return fmt.Errorf("expected error to contain either "+
×
1866
                                "'%s' or '%s' but was: '%v'", "marked as i"+
×
1867
                                "zombie", "edge not found", err)
×
1868
                }
1869
        }, DefaultTimeout)
1870
        require.NoError(h, err, "timeout while checking that channel is not "+
×
1871
                "found in graph")
×
1872
}
1873

1874
// AssertChannelInGraphDB asserts that a given channel is found in the graph db.
1875
func (h *HarnessTest) AssertChannelInGraphDB(hn *node.HarnessNode,
1876
        chanPoint *lnrpc.ChannelPoint) *lnrpc.ChannelEdge {
×
1877

×
1878
        ctxt, cancel := context.WithCancel(h.runCtx)
×
1879
        defer cancel()
×
1880

×
1881
        var edge *lnrpc.ChannelEdge
×
1882

×
1883
        op := h.OutPointFromChannelPoint(chanPoint)
×
1884
        err := wait.NoError(func() error {
×
1885
                resp, err := hn.RPC.LN.GetChanInfo(
×
1886
                        ctxt, &lnrpc.ChanInfoRequest{
×
1887
                                ChanPoint: op.String(),
×
1888
                        },
×
1889
                )
×
1890
                if err != nil {
×
1891
                        return fmt.Errorf("channel %s not found in graph: %w",
×
1892
                                op, err)
×
1893
                }
×
1894

1895
                // Make sure the policies are populated, otherwise this edge
1896
                // cannot be used for routing.
1897
                if resp.Node1Policy == nil {
×
1898
                        return fmt.Errorf("channel %s has no policy1", op)
×
1899
                }
×
1900

1901
                if resp.Node2Policy == nil {
×
1902
                        return fmt.Errorf("channel %s has no policy2", op)
×
1903
                }
×
1904

1905
                edge = resp
×
1906

×
1907
                return nil
×
1908
        }, DefaultTimeout)
1909

1910
        require.NoError(h, err, "%s: timeout finding channel in graph",
×
1911
                hn.Name())
×
1912

×
1913
        return edge
×
1914
}
1915

1916
// AssertChannelInGraphCache asserts a given channel is found in the graph
1917
// cache.
1918
func (h *HarnessTest) AssertChannelInGraphCache(hn *node.HarnessNode,
1919
        chanPoint *lnrpc.ChannelPoint) *lnrpc.ChannelEdge {
×
1920

×
1921
        var edge *lnrpc.ChannelEdge
×
1922

×
1923
        req := &lnrpc.ChannelGraphRequest{IncludeUnannounced: true}
×
1924
        cpStr := channelPointStr(chanPoint)
×
1925

×
1926
        err := wait.NoError(func() error {
×
1927
                chanGraph := hn.RPC.DescribeGraph(req)
×
1928

×
1929
                // Iterate all the known edges, and make sure the edge policies
×
1930
                // are populated when a matched edge is found.
×
1931
                for _, e := range chanGraph.Edges {
×
1932
                        if e.ChanPoint != cpStr {
×
1933
                                continue
×
1934
                        }
1935

1936
                        if e.Node1Policy == nil {
×
1937
                                return fmt.Errorf("no policy for node1 %v",
×
1938
                                        e.Node1Pub)
×
1939
                        }
×
1940

1941
                        if e.Node2Policy == nil {
×
1942
                                return fmt.Errorf("no policy for node2 %v",
×
1943
                                        e.Node1Pub)
×
1944
                        }
×
1945

1946
                        edge = e
×
1947

×
1948
                        return nil
×
1949
                }
1950

1951
                // If we've iterated over all the known edges and we weren't
1952
                // able to find this specific one, then we'll fail.
1953
                return fmt.Errorf("no edge found for channel point: %s", cpStr)
×
1954
        }, DefaultTimeout)
1955

1956
        require.NoError(h, err, "%s: timeout finding channel %v in graph cache",
×
1957
                cpStr, hn.Name())
×
1958

×
1959
        return edge
×
1960
}
1961

1962
// AssertChannelInGraphDB asserts that a given channel is found both in the
1963
// graph db (GetChanInfo) and the graph cache (DescribeGraph).
1964
func (h *HarnessTest) AssertChannelInGraph(hn *node.HarnessNode,
1965
        chanPoint *lnrpc.ChannelPoint) *lnrpc.ChannelEdge {
×
1966

×
1967
        // Make sure the channel is found in the db first.
×
1968
        h.AssertChannelInGraphDB(hn, chanPoint)
×
1969

×
1970
        // Assert the channel is also found in the graph cache, which refreshes
×
1971
        // every `--caches.rpc-graph-cache-duration`.
×
1972
        return h.AssertChannelInGraphCache(hn, chanPoint)
×
1973
}
×
1974

1975
// AssertTxAtHeight gets all of the transactions that a node's wallet has a
1976
// record of at the target height, and finds and returns the tx with the target
1977
// txid, failing if it is not found.
1978
func (h *HarnessTest) AssertTxAtHeight(hn *node.HarnessNode, height int32,
1979
        txid *chainhash.Hash) *lnrpc.Transaction {
×
1980

×
1981
        req := &lnrpc.GetTransactionsRequest{
×
1982
                StartHeight: height,
×
1983
                EndHeight:   height,
×
1984
        }
×
1985
        txns := hn.RPC.GetTransactions(req)
×
1986

×
1987
        for _, tx := range txns.Transactions {
×
1988
                if tx.TxHash == txid.String() {
×
1989
                        return tx
×
1990
                }
×
1991
        }
1992

1993
        require.Failf(h, "fail to find tx", "tx:%v not found at height:%v",
×
1994
                txid, height)
×
1995

×
1996
        return nil
×
1997
}
1998

1999
// getChannelPolicies queries the channel graph and retrieves the current edge
2000
// policies for the provided channel point.
2001
func (h *HarnessTest) getChannelPolicies(hn *node.HarnessNode,
2002
        advertisingNode string,
2003
        cp *lnrpc.ChannelPoint) (*lnrpc.RoutingPolicy, error) {
×
2004

×
2005
        req := &lnrpc.ChannelGraphRequest{IncludeUnannounced: true}
×
2006
        chanGraph := hn.RPC.DescribeGraph(req)
×
2007

×
2008
        cpStr := channelPointStr(cp)
×
2009
        for _, e := range chanGraph.Edges {
×
2010
                if e.ChanPoint != cpStr {
×
2011
                        continue
×
2012
                }
2013

2014
                if e.Node1Pub == advertisingNode {
×
2015
                        return e.Node1Policy, nil
×
2016
                }
×
2017

2018
                return e.Node2Policy, nil
×
2019
        }
2020

2021
        // If we've iterated over all the known edges and we weren't
2022
        // able to find this specific one, then we'll fail.
2023
        return nil, fmt.Errorf("did not find edge with advertisingNode: %s"+
×
2024
                ", channel point: %s", advertisingNode, cpStr)
×
2025
}
2026

2027
// AssertChannelPolicy asserts that the passed node's known channel policy for
2028
// the passed chanPoint is consistent with the expected policy values.
2029
func (h *HarnessTest) AssertChannelPolicy(hn *node.HarnessNode,
2030
        advertisingNode string, expectedPolicy *lnrpc.RoutingPolicy,
2031
        chanPoint *lnrpc.ChannelPoint) {
×
2032

×
2033
        policy, err := h.getChannelPolicies(hn, advertisingNode, chanPoint)
×
2034
        require.NoErrorf(h, err, "%s: failed to find policy", hn.Name())
×
2035

×
2036
        err = node.CheckChannelPolicy(policy, expectedPolicy)
×
2037
        require.NoErrorf(h, err, "%s: check policy failed", hn.Name())
×
2038
}
×
2039

2040
// AssertNumPolicyUpdates asserts that a given number of channel policy updates
2041
// has been seen in the specified node.
2042
func (h *HarnessTest) AssertNumPolicyUpdates(hn *node.HarnessNode,
2043
        chanPoint *lnrpc.ChannelPoint,
2044
        advertisingNode *node.HarnessNode, num int) {
×
2045

×
2046
        op := h.OutPointFromChannelPoint(chanPoint)
×
2047

×
2048
        var policies []*node.PolicyUpdateInfo
×
2049

×
2050
        err := wait.NoError(func() error {
×
2051
                policyMap := hn.Watcher.GetPolicyUpdates(op)
×
2052
                nodePolicy, ok := policyMap[advertisingNode.PubKeyStr]
×
2053
                if ok {
×
2054
                        policies = nodePolicy
×
2055
                }
×
2056

2057
                if len(policies) == num {
×
2058
                        return nil
×
2059
                }
×
2060

2061
                p, err := json.MarshalIndent(policies, "", "\t")
×
2062
                require.NoError(h, err, "encode policy err")
×
2063

×
2064
                return fmt.Errorf("expected to find %d policy updates, "+
×
2065
                        "instead got: %d, chanPoint: %v, "+
×
2066
                        "advertisingNode: %s:%s, policy: %s", num,
×
2067
                        len(policies), op, advertisingNode.Name(),
×
2068
                        advertisingNode.PubKeyStr, p)
×
2069
        }, DefaultTimeout)
2070

2071
        require.NoError(h, err, "%s: timeout waiting for num of policy updates",
×
2072
                hn.Name())
×
2073
}
2074

2075
// AssertNumPayments asserts that the number of payments made within the test
2076
// scope is as expected, including the incomplete ones.
2077
func (h *HarnessTest) AssertNumPayments(hn *node.HarnessNode,
2078
        num int) []*lnrpc.Payment {
×
2079

×
2080
        // Get the number of payments we already have from the previous test.
×
2081
        have := hn.State.Payment.Total
×
2082

×
2083
        req := &lnrpc.ListPaymentsRequest{
×
2084
                IncludeIncomplete: true,
×
2085
                IndexOffset:       hn.State.Payment.LastIndexOffset,
×
2086
        }
×
2087

×
2088
        var payments []*lnrpc.Payment
×
2089
        err := wait.NoError(func() error {
×
2090
                resp := hn.RPC.ListPayments(req)
×
2091

×
2092
                payments = resp.Payments
×
2093
                if len(payments) == num {
×
2094
                        return nil
×
2095
                }
×
2096

2097
                return errNumNotMatched(hn.Name(), "num of payments",
×
2098
                        num, len(payments), have+len(payments), have)
×
2099
        }, DefaultTimeout)
2100
        require.NoError(h, err, "%s: timeout checking num of payments",
×
2101
                hn.Name())
×
2102

×
2103
        return payments
×
2104
}
2105

2106
// AssertNumNodeAnns asserts that a given number of node announcements has been
2107
// seen in the specified node.
2108
func (h *HarnessTest) AssertNumNodeAnns(hn *node.HarnessNode,
2109
        pubkey string, num int) []*lnrpc.NodeUpdate {
×
2110

×
2111
        // We will get the current number of channel updates first and add it
×
2112
        // to our expected number of newly created channel updates.
×
2113
        anns, err := hn.Watcher.WaitForNumNodeUpdates(pubkey, num)
×
2114
        require.NoError(h, err, "%s: failed to assert num of node anns",
×
2115
                hn.Name())
×
2116

×
2117
        return anns
×
2118
}
×
2119

2120
// AssertNumChannelUpdates asserts that a given number of channel updates has
2121
// been seen in the specified node's network topology.
2122
func (h *HarnessTest) AssertNumChannelUpdates(hn *node.HarnessNode,
2123
        chanPoint *lnrpc.ChannelPoint, num int) {
×
2124

×
2125
        op := h.OutPointFromChannelPoint(chanPoint)
×
2126
        err := hn.Watcher.WaitForNumChannelUpdates(op, num)
×
2127
        require.NoError(h, err, "%s: failed to assert num of channel updates",
×
2128
                hn.Name())
×
2129
}
×
2130

2131
// CreateBurnAddr creates a random burn address of the given type.
2132
func (h *HarnessTest) CreateBurnAddr(addrType lnrpc.AddressType) ([]byte,
2133
        btcutil.Address) {
×
2134

×
2135
        randomPrivKey, err := btcec.NewPrivateKey()
×
2136
        require.NoError(h, err)
×
2137

×
2138
        randomKeyBytes := randomPrivKey.PubKey().SerializeCompressed()
×
2139
        harnessNetParams := miner.HarnessNetParams
×
2140

×
2141
        var addr btcutil.Address
×
2142
        switch addrType {
×
2143
        case lnrpc.AddressType_WITNESS_PUBKEY_HASH:
×
2144
                addr, err = btcutil.NewAddressWitnessPubKeyHash(
×
2145
                        btcutil.Hash160(randomKeyBytes), harnessNetParams,
×
2146
                )
×
2147

2148
        case lnrpc.AddressType_TAPROOT_PUBKEY:
×
2149
                taprootKey := txscript.ComputeTaprootKeyNoScript(
×
2150
                        randomPrivKey.PubKey(),
×
2151
                )
×
2152
                addr, err = btcutil.NewAddressPubKey(
×
2153
                        schnorr.SerializePubKey(taprootKey), harnessNetParams,
×
2154
                )
×
2155

2156
        case lnrpc.AddressType_NESTED_PUBKEY_HASH:
×
2157
                var witnessAddr btcutil.Address
×
2158
                witnessAddr, err = btcutil.NewAddressWitnessPubKeyHash(
×
2159
                        btcutil.Hash160(randomKeyBytes), harnessNetParams,
×
2160
                )
×
2161
                require.NoError(h, err)
×
2162

×
2163
                addr, err = btcutil.NewAddressScriptHash(
×
2164
                        h.PayToAddrScript(witnessAddr), harnessNetParams,
×
2165
                )
×
2166

2167
        default:
×
2168
                h.Fatalf("Unsupported burn address type: %v", addrType)
×
2169
        }
2170
        require.NoError(h, err)
×
2171

×
2172
        return h.PayToAddrScript(addr), addr
×
2173
}
2174

2175
// ReceiveTrackPayment waits until a message is received on the track payment
2176
// stream or the timeout is reached.
2177
func (h *HarnessTest) ReceiveTrackPayment(
2178
        stream rpc.TrackPaymentClient) *lnrpc.Payment {
×
2179

×
2180
        chanMsg := make(chan *lnrpc.Payment)
×
2181
        errChan := make(chan error)
×
2182
        go func() {
×
2183
                // Consume one message. This will block until the message is
×
2184
                // received.
×
2185
                resp, err := stream.Recv()
×
2186
                if err != nil {
×
2187
                        errChan <- err
×
2188
                        return
×
2189
                }
×
2190
                chanMsg <- resp
×
2191
        }()
2192

2193
        select {
×
2194
        case <-time.After(DefaultTimeout):
×
2195
                require.Fail(h, "timeout", "timeout trakcing payment")
×
2196

2197
        case err := <-errChan:
×
2198
                require.Failf(h, "err from stream",
×
2199
                        "received err from stream: %v", err)
×
2200

2201
        case updateMsg := <-chanMsg:
×
2202
                return updateMsg
×
2203
        }
2204

2205
        return nil
×
2206
}
2207

2208
// ReceiveHtlcEvent waits until a message is received on the subscribe
2209
// htlc event stream or the timeout is reached.
2210
func (h *HarnessTest) ReceiveHtlcEvent(
2211
        stream rpc.HtlcEventsClient) *routerrpc.HtlcEvent {
×
2212

×
2213
        chanMsg := make(chan *routerrpc.HtlcEvent)
×
2214
        errChan := make(chan error)
×
2215
        go func() {
×
2216
                // Consume one message. This will block until the message is
×
2217
                // received.
×
2218
                resp, err := stream.Recv()
×
2219
                if err != nil {
×
2220
                        errChan <- err
×
2221
                        return
×
2222
                }
×
2223
                chanMsg <- resp
×
2224
        }()
2225

2226
        select {
×
2227
        case <-time.After(DefaultTimeout):
×
2228
                require.Fail(h, "timeout", "timeout receiving htlc "+
×
2229
                        "event update")
×
2230

2231
        case err := <-errChan:
×
2232
                require.Failf(h, "err from stream",
×
2233
                        "received err from stream: %v", err)
×
2234

2235
        case updateMsg := <-chanMsg:
×
2236
                return updateMsg
×
2237
        }
2238

2239
        return nil
×
2240
}
2241

2242
// AssertHtlcEventType consumes one event from a client and asserts the event
2243
// type is matched.
2244
func (h *HarnessTest) AssertHtlcEventType(client rpc.HtlcEventsClient,
2245
        userType routerrpc.HtlcEvent_EventType) *routerrpc.HtlcEvent {
×
2246

×
2247
        event := h.ReceiveHtlcEvent(client)
×
2248
        require.Equalf(h, userType, event.EventType, "wrong event type, "+
×
2249
                "want %v got %v", userType, event.EventType)
×
2250

×
2251
        return event
×
2252
}
×
2253

2254
// HtlcEvent maps the series of event types used in `*routerrpc.HtlcEvent_*`.
2255
type HtlcEvent int
2256

2257
const (
2258
        HtlcEventForward HtlcEvent = iota
2259
        HtlcEventForwardFail
2260
        HtlcEventSettle
2261
        HtlcEventLinkFail
2262
        HtlcEventFinal
2263
)
2264

2265
// AssertHtlcEventType consumes one event from a client and asserts both the
2266
// user event type the event.Event type is matched.
2267
func (h *HarnessTest) AssertHtlcEventTypes(client rpc.HtlcEventsClient,
2268
        userType routerrpc.HtlcEvent_EventType,
2269
        eventType HtlcEvent) *routerrpc.HtlcEvent {
×
2270

×
2271
        event := h.ReceiveHtlcEvent(client)
×
2272
        require.Equalf(h, userType, event.EventType, "wrong event type, "+
×
2273
                "want %v got %v", userType, event.EventType)
×
2274

×
2275
        var ok bool
×
2276

×
2277
        switch eventType {
×
2278
        case HtlcEventForward:
×
2279
                _, ok = event.Event.(*routerrpc.HtlcEvent_ForwardEvent)
×
2280

2281
        case HtlcEventForwardFail:
×
2282
                _, ok = event.Event.(*routerrpc.HtlcEvent_ForwardFailEvent)
×
2283

2284
        case HtlcEventSettle:
×
2285
                _, ok = event.Event.(*routerrpc.HtlcEvent_SettleEvent)
×
2286

2287
        case HtlcEventLinkFail:
×
2288
                _, ok = event.Event.(*routerrpc.HtlcEvent_LinkFailEvent)
×
2289

2290
        case HtlcEventFinal:
×
2291
                _, ok = event.Event.(*routerrpc.HtlcEvent_FinalHtlcEvent)
×
2292
        }
2293

2294
        require.Truef(h, ok, "wrong event type: %T, want %T", event.Event,
×
2295
                eventType)
×
2296

×
2297
        return event
×
2298
}
2299

2300
// AssertFeeReport checks that the fee report from the given node has the
2301
// desired day, week, and month sum values.
2302
func (h *HarnessTest) AssertFeeReport(hn *node.HarnessNode,
2303
        day, week, month int) {
×
2304

×
2305
        err := wait.NoError(func() error {
×
2306
                feeReport, err := hn.RPC.LN.FeeReport(
×
2307
                        h.runCtx, &lnrpc.FeeReportRequest{},
×
2308
                )
×
2309
                require.NoError(h, err, "unable to query for fee report")
×
2310

×
2311
                if uint64(day) != feeReport.DayFeeSum {
×
2312
                        return fmt.Errorf("day fee mismatch, want %d, got %d",
×
2313
                                day, feeReport.DayFeeSum)
×
2314
                }
×
2315

2316
                if uint64(week) != feeReport.WeekFeeSum {
×
2317
                        return fmt.Errorf("week fee mismatch, want %d, got %d",
×
2318
                                week, feeReport.WeekFeeSum)
×
2319
                }
×
2320
                if uint64(month) != feeReport.MonthFeeSum {
×
2321
                        return fmt.Errorf("month fee mismatch, want %d, got %d",
×
2322
                                month, feeReport.MonthFeeSum)
×
2323
                }
×
2324

2325
                return nil
×
2326
        }, wait.DefaultTimeout)
2327
        require.NoErrorf(h, err, "%s: time out checking fee report", hn.Name())
×
2328
}
2329

2330
// AssertHtlcEvents consumes events from a client and ensures that they are of
2331
// the expected type and contain the expected number of forwards, forward
2332
// failures and settles.
2333
//
2334
// TODO(yy): needs refactor to reduce its complexity.
2335
func (h *HarnessTest) AssertHtlcEvents(client rpc.HtlcEventsClient,
2336
        fwdCount, fwdFailCount, settleCount, linkFailCount int,
2337
        userType routerrpc.HtlcEvent_EventType) []*routerrpc.HtlcEvent {
×
2338

×
2339
        var forwards, forwardFails, settles, linkFails int
×
2340

×
2341
        numEvents := fwdCount + fwdFailCount + settleCount + linkFailCount
×
2342
        events := make([]*routerrpc.HtlcEvent, 0)
×
2343

×
2344
        // It's either the userType or the unknown type.
×
2345
        //
×
2346
        // TODO(yy): maybe the FinalHtlcEvent shouldn't be in UNKNOWN type?
×
2347
        eventTypes := []routerrpc.HtlcEvent_EventType{
×
2348
                userType, routerrpc.HtlcEvent_UNKNOWN,
×
2349
        }
×
2350

×
2351
        for i := 0; i < numEvents; i++ {
×
2352
                event := h.ReceiveHtlcEvent(client)
×
2353

×
2354
                require.Containsf(h, eventTypes, event.EventType,
×
2355
                        "wrong event type, want %v, got %v", userType,
×
2356
                        event.EventType)
×
2357

×
2358
                events = append(events, event)
×
2359

×
2360
                switch e := event.Event.(type) {
×
2361
                case *routerrpc.HtlcEvent_ForwardEvent:
×
2362
                        forwards++
×
2363

2364
                case *routerrpc.HtlcEvent_ForwardFailEvent:
×
2365
                        forwardFails++
×
2366

2367
                case *routerrpc.HtlcEvent_SettleEvent:
×
2368
                        settles++
×
2369

2370
                case *routerrpc.HtlcEvent_FinalHtlcEvent:
×
2371
                        if e.FinalHtlcEvent.Settled {
×
2372
                                settles++
×
2373
                        }
×
2374

2375
                case *routerrpc.HtlcEvent_LinkFailEvent:
×
2376
                        linkFails++
×
2377

2378
                default:
×
2379
                        require.Fail(h, "assert event fail",
×
2380
                                "unexpected event: %T", event.Event)
×
2381
                }
2382
        }
2383

2384
        require.Equal(h, fwdCount, forwards, "num of forwards mismatch")
×
2385
        require.Equal(h, fwdFailCount, forwardFails,
×
2386
                "num of forward fails mismatch")
×
2387
        require.Equal(h, settleCount, settles, "num of settles mismatch")
×
2388
        require.Equal(h, linkFailCount, linkFails, "num of link fails mismatch")
×
2389

×
2390
        return events
×
2391
}
2392

2393
// AssertTransactionInWallet asserts a given txid can be found in the node's
2394
// wallet.
2395
func (h *HarnessTest) AssertTransactionInWallet(hn *node.HarnessNode,
2396
        txid chainhash.Hash) {
×
2397

×
2398
        req := &lnrpc.GetTransactionsRequest{}
×
2399
        err := wait.NoError(func() error {
×
2400
                txResp := hn.RPC.GetTransactions(req)
×
2401
                for _, txn := range txResp.Transactions {
×
2402
                        if txn.TxHash == txid.String() {
×
2403
                                return nil
×
2404
                        }
×
2405
                }
2406

2407
                return fmt.Errorf("%s: expected txid=%v not found in wallet",
×
2408
                        hn.Name(), txid)
×
2409
        }, DefaultTimeout)
2410

2411
        require.NoError(h, err, "failed to find tx")
×
2412
}
2413

2414
// AssertTransactionNotInWallet asserts a given txid can NOT be found in the
2415
// node's wallet.
2416
func (h *HarnessTest) AssertTransactionNotInWallet(hn *node.HarnessNode,
2417
        txid chainhash.Hash) {
×
2418

×
2419
        req := &lnrpc.GetTransactionsRequest{}
×
2420
        err := wait.NoError(func() error {
×
2421
                txResp := hn.RPC.GetTransactions(req)
×
2422
                for _, txn := range txResp.Transactions {
×
2423
                        if txn.TxHash == txid.String() {
×
2424
                                return fmt.Errorf("expected txid=%v to be "+
×
2425
                                        "not found", txid)
×
2426
                        }
×
2427
                }
2428

2429
                return nil
×
2430
        }, DefaultTimeout)
2431

2432
        require.NoErrorf(h, err, "%s: failed to assert tx not found", hn.Name())
×
2433
}
2434

2435
// WaitForNodeBlockHeight queries the node for its current block height until
2436
// it reaches the passed height.
2437
func (h *HarnessTest) WaitForNodeBlockHeight(hn *node.HarnessNode,
2438
        height int32) {
×
2439

×
2440
        err := wait.NoError(func() error {
×
2441
                info := hn.RPC.GetInfo()
×
2442
                if int32(info.BlockHeight) != height {
×
2443
                        return fmt.Errorf("expected block height to "+
×
2444
                                "be %v, was %v", height, info.BlockHeight)
×
2445
                }
×
2446

2447
                return nil
×
2448
        }, DefaultTimeout)
2449

2450
        require.NoErrorf(h, err, "%s: timeout while waiting for height",
×
2451
                hn.Name())
×
2452
}
2453

2454
// AssertChannelCommitHeight asserts the given channel for the node has the
2455
// expected commit height(`NumUpdates`).
2456
func (h *HarnessTest) AssertChannelCommitHeight(hn *node.HarnessNode,
2457
        cp *lnrpc.ChannelPoint, height int) {
×
2458

×
2459
        err := wait.NoError(func() error {
×
2460
                c, err := h.findChannel(hn, cp)
×
2461
                if err != nil {
×
2462
                        return err
×
2463
                }
×
2464

2465
                if int(c.NumUpdates) == height {
×
2466
                        return nil
×
2467
                }
×
2468

2469
                return fmt.Errorf("expected commit height to be %v, was %v",
×
2470
                        height, c.NumUpdates)
×
2471
        }, DefaultTimeout)
2472

2473
        require.NoError(h, err, "timeout while waiting for commit height")
×
2474
}
2475

2476
// AssertNumInvoices asserts that the number of invoices made within the test
2477
// scope is as expected.
2478
func (h *HarnessTest) AssertNumInvoices(hn *node.HarnessNode,
2479
        num int) []*lnrpc.Invoice {
×
2480

×
2481
        have := hn.State.Invoice.Total
×
2482
        req := &lnrpc.ListInvoiceRequest{
×
2483
                NumMaxInvoices: math.MaxUint64,
×
2484
                IndexOffset:    hn.State.Invoice.LastIndexOffset,
×
2485
        }
×
2486

×
2487
        var invoices []*lnrpc.Invoice
×
2488
        err := wait.NoError(func() error {
×
2489
                resp := hn.RPC.ListInvoices(req)
×
2490

×
2491
                invoices = resp.Invoices
×
2492
                if len(invoices) == num {
×
2493
                        return nil
×
2494
                }
×
2495

2496
                return errNumNotMatched(hn.Name(), "num of invoices",
×
2497
                        num, len(invoices), have+len(invoices), have)
×
2498
        }, DefaultTimeout)
2499
        require.NoError(h, err, "timeout checking num of invoices")
×
2500

×
2501
        return invoices
×
2502
}
2503

2504
// ReceiveSendToRouteUpdate waits until a message is received on the
2505
// SendToRoute client stream or the timeout is reached.
2506
func (h *HarnessTest) ReceiveSendToRouteUpdate(
2507
        stream rpc.SendToRouteClient) (*lnrpc.SendResponse, error) {
×
2508

×
2509
        chanMsg := make(chan *lnrpc.SendResponse, 1)
×
2510
        errChan := make(chan error, 1)
×
2511
        go func() {
×
2512
                // Consume one message. This will block until the message is
×
2513
                // received.
×
2514
                resp, err := stream.Recv()
×
2515
                if err != nil {
×
2516
                        errChan <- err
×
2517

×
2518
                        return
×
2519
                }
×
2520
                chanMsg <- resp
×
2521
        }()
2522

2523
        select {
×
2524
        case <-time.After(DefaultTimeout):
×
2525
                require.Fail(h, "timeout", "timeout waiting for send resp")
×
2526
                return nil, nil
×
2527

2528
        case err := <-errChan:
×
2529
                return nil, err
×
2530

2531
        case updateMsg := <-chanMsg:
×
2532
                return updateMsg, nil
×
2533
        }
2534
}
2535

2536
// AssertInvoiceEqual asserts that two lnrpc.Invoices are equivalent. A custom
2537
// comparison function is defined for these tests, since proto message returned
2538
// from unary and streaming RPCs (as of protobuf 1.23.0 and grpc 1.29.1) aren't
2539
// consistent with the private fields set on the messages. As a result, we
2540
// avoid using require.Equal and test only the actual data members.
2541
func (h *HarnessTest) AssertInvoiceEqual(a, b *lnrpc.Invoice) {
×
2542
        // Ensure the HTLCs are sorted properly before attempting to compare.
×
2543
        sort.Slice(a.Htlcs, func(i, j int) bool {
×
2544
                return a.Htlcs[i].ChanId < a.Htlcs[j].ChanId
×
2545
        })
×
2546
        sort.Slice(b.Htlcs, func(i, j int) bool {
×
2547
                return b.Htlcs[i].ChanId < b.Htlcs[j].ChanId
×
2548
        })
×
2549

2550
        require.Equal(h, a.Memo, b.Memo)
×
2551
        require.Equal(h, a.RPreimage, b.RPreimage)
×
2552
        require.Equal(h, a.RHash, b.RHash)
×
2553
        require.Equal(h, a.Value, b.Value)
×
2554
        require.Equal(h, a.ValueMsat, b.ValueMsat)
×
2555
        require.Equal(h, a.CreationDate, b.CreationDate)
×
2556
        require.Equal(h, a.SettleDate, b.SettleDate)
×
2557
        require.Equal(h, a.PaymentRequest, b.PaymentRequest)
×
2558
        require.Equal(h, a.DescriptionHash, b.DescriptionHash)
×
2559
        require.Equal(h, a.Expiry, b.Expiry)
×
2560
        require.Equal(h, a.FallbackAddr, b.FallbackAddr)
×
2561
        require.Equal(h, a.CltvExpiry, b.CltvExpiry)
×
2562
        require.Equal(h, a.RouteHints, b.RouteHints)
×
2563
        require.Equal(h, a.Private, b.Private)
×
2564
        require.Equal(h, a.AddIndex, b.AddIndex)
×
2565
        require.Equal(h, a.SettleIndex, b.SettleIndex)
×
2566
        require.Equal(h, a.AmtPaidSat, b.AmtPaidSat)
×
2567
        require.Equal(h, a.AmtPaidMsat, b.AmtPaidMsat)
×
2568
        require.Equal(h, a.State, b.State)
×
2569
        require.Equal(h, a.Features, b.Features)
×
2570
        require.Equal(h, a.IsKeysend, b.IsKeysend)
×
2571
        require.Equal(h, a.PaymentAddr, b.PaymentAddr)
×
2572
        require.Equal(h, a.IsAmp, b.IsAmp)
×
2573

×
2574
        require.Equal(h, len(a.Htlcs), len(b.Htlcs))
×
2575
        for i := range a.Htlcs {
×
2576
                htlcA, htlcB := a.Htlcs[i], b.Htlcs[i]
×
2577
                require.Equal(h, htlcA.ChanId, htlcB.ChanId)
×
2578
                require.Equal(h, htlcA.HtlcIndex, htlcB.HtlcIndex)
×
2579
                require.Equal(h, htlcA.AmtMsat, htlcB.AmtMsat)
×
2580
                require.Equal(h, htlcA.AcceptHeight, htlcB.AcceptHeight)
×
2581
                require.Equal(h, htlcA.AcceptTime, htlcB.AcceptTime)
×
2582
                require.Equal(h, htlcA.ResolveTime, htlcB.ResolveTime)
×
2583
                require.Equal(h, htlcA.ExpiryHeight, htlcB.ExpiryHeight)
×
2584
                require.Equal(h, htlcA.State, htlcB.State)
×
2585
                require.Equal(h, htlcA.CustomRecords, htlcB.CustomRecords)
×
2586
                require.Equal(h, htlcA.MppTotalAmtMsat, htlcB.MppTotalAmtMsat)
×
2587
                require.Equal(h, htlcA.Amp, htlcB.Amp)
×
2588
        }
×
2589
}
2590

2591
// AssertUTXOInWallet asserts that a given UTXO can be found in the node's
2592
// wallet.
2593
func (h *HarnessTest) AssertUTXOInWallet(hn *node.HarnessNode,
2594
        op *lnrpc.OutPoint, account string) {
×
2595

×
2596
        err := wait.NoError(func() error {
×
2597
                utxos := h.GetUTXOs(hn, account)
×
2598

×
2599
                err := fmt.Errorf("tx with hash %x not found", op.TxidBytes)
×
2600
                for _, utxo := range utxos {
×
2601
                        if !bytes.Equal(utxo.Outpoint.TxidBytes, op.TxidBytes) {
×
2602
                                continue
×
2603
                        }
2604

2605
                        err = fmt.Errorf("tx with output index %v not found",
×
2606
                                op.OutputIndex)
×
2607
                        if utxo.Outpoint.OutputIndex != op.OutputIndex {
×
2608
                                continue
×
2609
                        }
2610

2611
                        return nil
×
2612
                }
2613

2614
                return err
×
2615
        }, DefaultTimeout)
2616

2617
        require.NoErrorf(h, err, "outpoint %v not found in %s's wallet",
×
2618
                op, hn.Name())
×
2619
}
2620

2621
// AssertWalletAccountBalance asserts that the unconfirmed and confirmed
2622
// balance for the given account is satisfied by the WalletBalance and
2623
// ListUnspent RPCs. The unconfirmed balance is not checked for neutrino nodes.
2624
func (h *HarnessTest) AssertWalletAccountBalance(hn *node.HarnessNode,
2625
        account string, confirmedBalance, unconfirmedBalance int64) {
×
2626

×
2627
        err := wait.NoError(func() error {
×
2628
                balanceResp := hn.RPC.WalletBalance()
×
2629
                require.Contains(h, balanceResp.AccountBalance, account)
×
2630
                accountBalance := balanceResp.AccountBalance[account]
×
2631

×
2632
                // Check confirmed balance.
×
2633
                if accountBalance.ConfirmedBalance != confirmedBalance {
×
2634
                        return fmt.Errorf("expected confirmed balance %v, "+
×
2635
                                "got %v", confirmedBalance,
×
2636
                                accountBalance.ConfirmedBalance)
×
2637
                }
×
2638

2639
                utxos := h.GetUTXOsConfirmed(hn, account)
×
2640
                var totalConfirmedVal int64
×
2641
                for _, utxo := range utxos {
×
2642
                        totalConfirmedVal += utxo.AmountSat
×
2643
                }
×
2644
                if totalConfirmedVal != confirmedBalance {
×
2645
                        return fmt.Errorf("expected total confirmed utxo "+
×
2646
                                "balance %v, got %v", confirmedBalance,
×
2647
                                totalConfirmedVal)
×
2648
                }
×
2649

2650
                // Skip unconfirmed balance checks for neutrino nodes.
2651
                if h.IsNeutrinoBackend() {
×
2652
                        return nil
×
2653
                }
×
2654

2655
                // Check unconfirmed balance.
2656
                if accountBalance.UnconfirmedBalance != unconfirmedBalance {
×
2657
                        return fmt.Errorf("expected unconfirmed balance %v, "+
×
2658
                                "got %v", unconfirmedBalance,
×
2659
                                accountBalance.UnconfirmedBalance)
×
2660
                }
×
2661

2662
                utxos = h.GetUTXOsUnconfirmed(hn, account)
×
2663
                var totalUnconfirmedVal int64
×
2664
                for _, utxo := range utxos {
×
2665
                        totalUnconfirmedVal += utxo.AmountSat
×
2666
                }
×
2667
                if totalUnconfirmedVal != unconfirmedBalance {
×
2668
                        return fmt.Errorf("expected total unconfirmed utxo "+
×
2669
                                "balance %v, got %v", unconfirmedBalance,
×
2670
                                totalUnconfirmedVal)
×
2671
                }
×
2672

2673
                return nil
×
2674
        }, DefaultTimeout)
2675
        require.NoError(h, err, "timeout checking wallet account balance")
×
2676
}
2677

2678
// AssertClosingTxInMempool assert that the closing transaction of the given
2679
// channel point can be found in the mempool. If the channel has anchors, it
2680
// will assert the anchor sweep tx is also in the mempool.
2681
func (h *HarnessTest) AssertClosingTxInMempool(cp *lnrpc.ChannelPoint,
2682
        c lnrpc.CommitmentType) *wire.MsgTx {
×
2683

×
2684
        // Get expected number of txes to be found in the mempool.
×
2685
        expectedTxes := 1
×
2686
        hasAnchors := CommitTypeHasAnchors(c)
×
2687
        if hasAnchors {
×
2688
                expectedTxes = 2
×
2689
        }
×
2690

2691
        // Wait for the expected txes to be found in the mempool.
2692
        h.AssertNumTxsInMempool(expectedTxes)
×
2693

×
2694
        // Get the closing tx from the mempool.
×
2695
        op := h.OutPointFromChannelPoint(cp)
×
2696
        closeTx := h.AssertOutpointInMempool(op)
×
2697

×
2698
        return closeTx
×
2699
}
2700

2701
// AssertClosingTxInMempool assert that the closing transaction of the given
2702
// channel point can be found in the mempool. If the channel has anchors, it
2703
// will assert the anchor sweep tx is also in the mempool.
2704
func (h *HarnessTest) MineClosingTx(cp *lnrpc.ChannelPoint) *wire.MsgTx {
×
2705
        // Wait for the expected txes to be found in the mempool.
×
2706
        h.AssertNumTxsInMempool(1)
×
2707

×
2708
        // Get the closing tx from the mempool.
×
2709
        op := h.OutPointFromChannelPoint(cp)
×
2710
        closeTx := h.AssertOutpointInMempool(op)
×
2711

×
2712
        // Mine a block to confirm the closing transaction and potential anchor
×
2713
        // sweep.
×
2714
        h.MineBlocksAndAssertNumTxes(1, 1)
×
2715

×
2716
        return closeTx
×
2717
}
×
2718

2719
// AssertWalletLockedBalance asserts the expected amount has been marked as
2720
// locked in the node's WalletBalance response.
2721
func (h *HarnessTest) AssertWalletLockedBalance(hn *node.HarnessNode,
2722
        balance int64) {
×
2723

×
2724
        err := wait.NoError(func() error {
×
2725
                balanceResp := hn.RPC.WalletBalance()
×
2726
                got := balanceResp.LockedBalance
×
2727

×
2728
                if got != balance {
×
2729
                        return fmt.Errorf("want %d, got %d", balance, got)
×
2730
                }
×
2731

2732
                return nil
×
2733
        }, wait.DefaultTimeout)
2734
        require.NoError(h, err, "%s: timeout checking locked balance",
×
2735
                hn.Name())
×
2736
}
2737

2738
// AssertNumPendingSweeps asserts the number of pending sweeps for the given
2739
// node.
2740
func (h *HarnessTest) AssertNumPendingSweeps(hn *node.HarnessNode,
2741
        n int) []*walletrpc.PendingSweep {
×
2742

×
2743
        results := make([]*walletrpc.PendingSweep, 0, n)
×
2744

×
2745
        err := wait.NoError(func() error {
×
2746
                resp := hn.RPC.PendingSweeps()
×
2747
                num := len(resp.PendingSweeps)
×
2748

×
2749
                numDesc := "\n"
×
2750
                for _, s := range resp.PendingSweeps {
×
2751
                        desc := fmt.Sprintf("op=%v:%v, amt=%v, type=%v, "+
×
2752
                                "deadline=%v, maturityHeight=%v\n",
×
2753
                                s.Outpoint.TxidStr, s.Outpoint.OutputIndex,
×
2754
                                s.AmountSat, s.WitnessType, s.DeadlineHeight,
×
2755
                                s.MaturityHeight)
×
2756
                        numDesc += desc
×
2757

×
2758
                        // The deadline height must be set, otherwise the
×
2759
                        // pending input response is not update-to-date.
×
2760
                        if s.DeadlineHeight == 0 {
×
2761
                                return fmt.Errorf("input not updated: %s", desc)
×
2762
                        }
×
2763
                }
2764

2765
                if num == n {
×
2766
                        results = resp.PendingSweeps
×
2767
                        return nil
×
2768
                }
×
2769

2770
                return fmt.Errorf("want %d , got %d, sweeps: %s", n, num,
×
2771
                        numDesc)
×
2772
        }, DefaultTimeout)
2773

2774
        require.NoErrorf(h, err, "%s: check pending sweeps timeout", hn.Name())
×
2775

×
2776
        return results
×
2777
}
2778

2779
// AssertAtLeastNumPendingSweeps asserts there are at least n pending sweeps for
2780
// the given node.
2781
func (h *HarnessTest) AssertAtLeastNumPendingSweeps(hn *node.HarnessNode,
2782
        n int) []*walletrpc.PendingSweep {
×
2783

×
2784
        results := make([]*walletrpc.PendingSweep, 0, n)
×
2785

×
2786
        err := wait.NoError(func() error {
×
2787
                resp := hn.RPC.PendingSweeps()
×
2788
                num := len(resp.PendingSweeps)
×
2789

×
2790
                numDesc := "\n"
×
2791
                for _, s := range resp.PendingSweeps {
×
2792
                        desc := fmt.Sprintf("op=%v:%v, amt=%v, type=%v, "+
×
2793
                                "deadline=%v, maturityHeight=%v\n",
×
2794
                                s.Outpoint.TxidStr, s.Outpoint.OutputIndex,
×
2795
                                s.AmountSat, s.WitnessType, s.DeadlineHeight,
×
2796
                                s.MaturityHeight)
×
2797
                        numDesc += desc
×
2798

×
2799
                        // The deadline height must be set, otherwise the
×
2800
                        // pending input response is not update-to-date.
×
2801
                        if s.DeadlineHeight == 0 {
×
2802
                                return fmt.Errorf("input not updated: %s", desc)
×
2803
                        }
×
2804
                }
2805

2806
                if num >= n {
×
2807
                        results = resp.PendingSweeps
×
2808
                        return nil
×
2809
                }
×
2810

2811
                return fmt.Errorf("want %d , got %d, sweeps: %s", n, num,
×
2812
                        numDesc)
×
2813
        }, DefaultTimeout)
2814

2815
        require.NoErrorf(h, err, "%s: check pending sweeps timeout", hn.Name())
×
2816

×
2817
        return results
×
2818
}
2819

2820
// FindSweepingTxns asserts the expected number of sweeping txns are found in
2821
// the txns specified and return them.
2822
func (h *HarnessTest) FindSweepingTxns(txns []*wire.MsgTx,
2823
        expectedNumSweeps int, closeTxid chainhash.Hash) []*wire.MsgTx {
×
2824

×
2825
        var sweepTxns []*wire.MsgTx
×
2826

×
2827
        for _, tx := range txns {
×
2828
                if tx.TxIn[0].PreviousOutPoint.Hash == closeTxid {
×
2829
                        sweepTxns = append(sweepTxns, tx)
×
2830
                }
×
2831
        }
2832
        require.Len(h, sweepTxns, expectedNumSweeps, "unexpected num of sweeps")
×
2833

×
2834
        return sweepTxns
×
2835
}
2836

2837
// AssertForceCloseAndAnchorTxnsInMempool asserts that the force close and
2838
// anchor sweep txns are found in the mempool and returns the force close tx
2839
// and the anchor sweep tx.
2840
func (h *HarnessTest) AssertForceCloseAndAnchorTxnsInMempool() (*wire.MsgTx,
2841
        *wire.MsgTx) {
×
2842

×
2843
        // Assert there are two txns in the mempool.
×
2844
        txns := h.GetNumTxsFromMempool(2)
×
2845

×
2846
        // isParentAndChild checks whether there is an input used in the
×
2847
        // assumed child tx by checking every input's previous outpoint against
×
2848
        // the assumed parentTxid.
×
2849
        isParentAndChild := func(parent, child *wire.MsgTx) bool {
×
2850
                parentTxid := parent.TxHash()
×
2851

×
2852
                for _, inp := range child.TxIn {
×
2853
                        if inp.PreviousOutPoint.Hash == parentTxid {
×
2854
                                // Found a match, this is indeed the anchor
×
2855
                                // sweeping tx so we return it here.
×
2856
                                return true
×
2857
                        }
×
2858
                }
2859

2860
                return false
×
2861
        }
2862

2863
        switch {
×
2864
        // Assume the first one is the closing tx and the second one is the
2865
        // anchor sweeping tx.
2866
        case isParentAndChild(txns[0], txns[1]):
×
2867
                return txns[0], txns[1]
×
2868

2869
        // Assume the first one is the anchor sweeping tx and the second one is
2870
        // the closing tx.
2871
        case isParentAndChild(txns[1], txns[0]):
×
2872
                return txns[1], txns[0]
×
2873

2874
        // Unrelated txns found, fail the test.
2875
        default:
×
2876
                h.Fatalf("the two txns not related: %v", txns)
×
2877

×
2878
                return nil, nil
×
2879
        }
2880
}
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