From e50007401780fc944be41ed18c9414096fcbf07f Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 11 Aug 2022 19:08:25 +0800 Subject: [PATCH] itest: refactor `testBidirectionalAsyncPayments` --- lntest/itest/list_on_test.go | 4 + lntest/itest/lnd_payment_test.go | 238 ++++++++------------------ lntest/itest/lnd_test_list_on_test.go | 7 +- 3 files changed, 78 insertions(+), 171 deletions(-) diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index f2531203f..dcf85817c 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -509,4 +509,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "zero conf reorg edge existence", TestFunc: testZeroConfReorg, }, + { + Name: "async bidirectional payments", + TestFunc: testBidirectionalAsyncPayments, + }, } diff --git a/lntest/itest/lnd_payment_test.go b/lntest/itest/lnd_payment_test.go index 590870285..e9005e6e9 100644 --- a/lntest/itest/lnd_payment_test.go +++ b/lntest/itest/lnd_payment_test.go @@ -1,7 +1,6 @@ package itest import ( - "context" "crypto/sha256" "encoding/hex" "fmt" @@ -304,46 +303,13 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) { // All payments have been sent, mark the finish time. timeTaken := time.Since(now) - // assertChannelState asserts the channel state by checking the values - // in fields, LocalBalance, RemoteBalance and num of PendingHtlcs. - assertChannelState := func(hn *node.HarnessNode, cp *lnrpc.ChannelPoint, - localBalance, remoteBalance int64, numPendingHtlcs int) { - - // Get the funding point. - err := wait.NoError(func() error { - // Find the target channel first. - target := ht.GetChannelByChanPoint(hn, cp) - - if len(target.PendingHtlcs) != numPendingHtlcs { - return fmt.Errorf("pending htlcs is "+ - "incorrect, got %v, expected %v", - len(target.PendingHtlcs), 0) - } - - if target.LocalBalance != localBalance { - return fmt.Errorf("local balance is "+ - "incorrect, got %v, expected %v", - target.LocalBalance, localBalance) - } - - if target.RemoteBalance != remoteBalance { - return fmt.Errorf("remote balance is "+ - "incorrect, got %v, expected %v", - target.RemoteBalance, remoteBalance) - } - - return nil - }, lntemp.DefaultTimeout) - require.NoError(ht, err, "timeout while chekcing for balance") - } - // Wait for the revocation to be received so alice no longer has // pending htlcs listed and has correct balances. This is needed due to // the fact that we now pipeline the settles. - assertChannelState(alice, chanPoint, aliceAmt, bobAmt, 0) + assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt) // Wait for Bob to receive revocation from Alice. - assertChannelState(bob, chanPoint, bobAmt, aliceAmt, 0) + assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt) ht.Log("\tBenchmark info: Elapsed time: ", timeTaken) ht.Log("\tBenchmark info: TPS: ", @@ -357,28 +323,28 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) { // testBidirectionalAsyncPayments tests that nodes are able to send the // payments to each other in async manner without blocking. -func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() +func testBidirectionalAsyncPayments(ht *lntemp.HarnessTest) { + const paymentAmt = 1000 - const ( - paymentAmt = 1000 - ) + // We use new nodes here as the benchmark test creates lots of data + // which can be costly to be carried on. + alice := ht.NewNode("Alice", []string{"--pending-commit-interval=3m"}) + bob := ht.NewNode("Bob", []string{"--pending-commit-interval=3m"}) + + ht.EnsureConnected(alice, bob) + ht.FundCoins(btcutil.SatoshiPerBitcoin, alice) // First establish a channel with a capacity equals to the overall // amount of payments, between Alice and Bob, at the end of the test // Alice should send all money from her side to Bob. - chanPoint := openChannelAndAssert( - t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ + chanPoint := ht.OpenChannel( + alice, bob, lntemp.OpenChannelParams{ Amt: paymentAmt * 2000, PushAmt: paymentAmt * 1000, }, ) - info, err := getChanInfo(net.Alice) - if err != nil { - t.Fatalf("unable to get alice channel info: %v", err) - } + info := ht.QueryChannelByChanPoint(alice, chanPoint) // We'll create a number of invoices equal the max number of HTLCs that // can be carried in one direction. The number on the commitment will @@ -394,155 +360,64 @@ func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) // With the channel open, we'll create invoices for Bob that Alice // will pay to in order to advance the state of the channel. - bobPayReqs, _, _, err := createPayReqs( - net.Bob, paymentAmt, numInvoices, - ) - if err != nil { - t.Fatalf("unable to create pay reqs: %v", err) - } + bobPayReqs, _, _ := ht.CreatePayReqs(bob, paymentAmt, numInvoices) // With the channel open, we'll create invoices for Alice that Bob // will pay to in order to advance the state of the channel. - alicePayReqs, _, _, err := createPayReqs( - net.Alice, paymentAmt, numInvoices, - ) - if err != nil { - t.Fatalf("unable to create pay reqs: %v", err) - } - - // Wait for Alice to receive the channel edge from the funding manager. - if err = net.Alice.WaitForNetworkChannelOpen(chanPoint); err != nil { - t.Fatalf("alice didn't see the alice->bob channel before "+ - "timeout: %v", err) - } - if err = net.Bob.WaitForNetworkChannelOpen(chanPoint); err != nil { - t.Fatalf("bob didn't see the bob->alice channel before "+ - "timeout: %v", err) - } + alicePayReqs, _, _ := ht.CreatePayReqs(alice, paymentAmt, numInvoices) // Reset mission control to prevent previous payment results from // interfering with this test. A new channel has been opened, but // mission control operates on node pairs. - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - _, err = net.Alice.RouterClient.ResetMissionControl( - ctxt, &routerrpc.ResetMissionControlRequest{}, - ) - if err != nil { - t.Fatalf("unable to reset mc for alice: %v", err) - } + alice.RPC.ResetMissionControl() // Send payments from Alice to Bob and from Bob to Alice in async // manner. - errChan := make(chan error) - statusChan := make(chan *lnrpc.Payment) + settled := make(chan struct{}) + defer close(settled) - send := func(node *lntest.HarnessNode, payReq string) { - go func() { - ctxt, _ = context.WithTimeout( - ctxb, lntest.AsyncBenchmarkTimeout, - ) - stream, err := node.RouterClient.SendPaymentV2( - ctxt, - &routerrpc.SendPaymentRequest{ - PaymentRequest: payReq, - TimeoutSeconds: 60, - FeeLimitMsat: noFeeLimitMsat, - }, - ) - if err != nil { - errChan <- err - } - result, err := getPaymentResult(stream) - if err != nil { - errChan <- err - } + timeout := lntest.AsyncBenchmarkTimeout * 4 + send := func(node *node.HarnessNode, payReq string) { + req := &routerrpc.SendPaymentRequest{ + PaymentRequest: payReq, + TimeoutSeconds: int32(timeout.Seconds()), + FeeLimitMsat: noFeeLimitMsat, + } + // AssertPaymentStatusWithTimeout will assert that the + // payment is settled. + stream := node.RPC.SendPayment(req) + ht.AssertPaymentSucceedWithTimeout(stream, timeout) - statusChan <- result - }() + settled <- struct{}{} } for i := 0; i < numInvoices; i++ { - send(net.Bob, alicePayReqs[i]) - send(net.Alice, bobPayReqs[i]) + go send(bob, alicePayReqs[i]) + go send(alice, bobPayReqs[i]) } // Expect all payments to succeed. + timer := time.After(timeout) for i := 0; i < 2*numInvoices; i++ { select { - case result := <-statusChan: - if result.Status != lnrpc.Payment_SUCCEEDED { - t.Fatalf("payment error: %v", result.Status) - } - - case err := <-errChan: - t.Fatalf("payment error: %v", err) + case <-settled: + case <-timer: + require.Fail(ht, "timeout", "wait payment failed") } } // Wait for Alice and Bob to receive revocations messages, and update // states, i.e. balance info. - err = wait.NoError(func() error { - aliceInfo, err := getChanInfo(net.Alice) - if err != nil { - t.Fatalf("unable to get alice's channel info: %v", err) - } - - if aliceInfo.RemoteBalance != bobAmt { - return fmt.Errorf("alice's remote balance is incorrect, "+ - "got %v, expected %v", aliceInfo.RemoteBalance, - bobAmt) - } - - if aliceInfo.LocalBalance != aliceAmt { - return fmt.Errorf("alice's local balance is incorrect, "+ - "got %v, expected %v", aliceInfo.LocalBalance, - aliceAmt) - } - - if len(aliceInfo.PendingHtlcs) != 0 { - return fmt.Errorf("alice's pending htlcs is incorrect, "+ - "got %v expected %v", - len(aliceInfo.PendingHtlcs), 0) - } - - return nil - }, defaultTimeout) - require.NoError(t.t, err) + assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt) // Next query for Bob's and Alice's channel states, in order to confirm // that all payment have been successful transmitted. - err = wait.NoError(func() error { - bobInfo, err := getChanInfo(net.Bob) - if err != nil { - t.Fatalf("unable to get bob's channel info: %v", err) - } - - if bobInfo.LocalBalance != bobAmt { - return fmt.Errorf("bob's local balance is incorrect, "+ - "got %v, expected %v", bobInfo.LocalBalance, - bobAmt) - } - - if bobInfo.RemoteBalance != aliceAmt { - return fmt.Errorf("bob's remote balance is incorrect, "+ - "got %v, expected %v", bobInfo.RemoteBalance, - aliceAmt) - } - - if len(bobInfo.PendingHtlcs) != 0 { - return fmt.Errorf("bob's pending htlcs is incorrect, "+ - "got %v, expected %v", - len(bobInfo.PendingHtlcs), 0) - } - - return nil - }, defaultTimeout) - require.NoError(t.t, err) + assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt) // Finally, immediately close the channel. This function will also // block until the channel is closed and will additionally assert the // relevant channel closing post conditions. - closeChannelAndAssert(t, net, net.Alice, chanPoint, false) + ht.CloseChannel(alice, chanPoint) } func testInvoiceSubscriptions(ht *lntemp.HarnessTest) { @@ -672,3 +547,36 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) { ht.CloseChannel(alice, chanPoint) } + +// assertChannelState asserts the channel state by checking the values in +// fields, LocalBalance, RemoteBalance and num of PendingHtlcs. +func assertChannelState(ht *lntemp.HarnessTest, hn *node.HarnessNode, + cp *lnrpc.ChannelPoint, localBalance, remoteBalance int64) { + + // Get the funding point. + err := wait.NoError(func() error { + // Find the target channel first. + target := ht.GetChannelByChanPoint(hn, cp) + + if len(target.PendingHtlcs) != 0 { + return fmt.Errorf("pending htlcs is "+ + "incorrect, got %v, expected %v", + len(target.PendingHtlcs), 0) + } + + if target.LocalBalance != localBalance { + return fmt.Errorf("local balance is "+ + "incorrect, got %v, expected %v", + target.LocalBalance, localBalance) + } + + if target.RemoteBalance != remoteBalance { + return fmt.Errorf("remote balance is "+ + "incorrect, got %v, expected %v", + target.RemoteBalance, remoteBalance) + } + + return nil + }, lntemp.DefaultTimeout) + require.NoError(ht, err, "timeout while chekcing for balance") +} diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index 0783688bd..d760ec2ce 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -3,9 +3,4 @@ package itest -var allTestCases = []*testCase{ - { - name: "async bidirectional payments", - test: testBidirectionalAsyncPayments, - }, -} +var allTestCases = []*testCase{}