From 874689719eb6d9ef112c9e11c19eca2e765eba7d Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 9 Aug 2022 19:09:59 +0800 Subject: [PATCH] itest: refactor `testSwitchOfflineDeliveryPersistence` --- lntest/itest/list_on_test.go | 4 + lntest/itest/lnd_switch_test.go | 253 +++----------------------- lntest/itest/lnd_test_list_on_test.go | 4 - 3 files changed, 29 insertions(+), 232 deletions(-) diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index 6fba40711..00259372c 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -377,4 +377,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "switch offline delivery", TestFunc: testSwitchOfflineDelivery, }, + { + Name: "switch offline delivery persistence", + TestFunc: testSwitchOfflineDeliveryPersistence, + }, } diff --git a/lntest/itest/lnd_switch_test.go b/lntest/itest/lnd_switch_test.go index 3a2a0958e..1c2a408dd 100644 --- a/lntest/itest/lnd_switch_test.go +++ b/lntest/itest/lnd_switch_test.go @@ -1,8 +1,6 @@ package itest import ( - "context" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/lnrpc" @@ -10,6 +8,7 @@ import ( "github.com/lightningnetwork/lnd/lntemp/node" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/stretchr/testify/require" ) const ( @@ -178,214 +177,48 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) { // 3. Carol --- Dave X Alice <-- Bob settle last hop // 4. Carol --- Dave X X Bob restart Alice // 5. Carol <-- Dave <-- Alice --- Bob expect settle to propagate -func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() - - const chanAmt = btcutil.Amount(1000000) - const pushAmt = btcutil.Amount(900000) - var networkChans []*lnrpc.ChannelPoint - - // Open a channel with 100k satoshis between Alice and Bob with Alice - // being the sole funder of the channel. - chanPointAlice := openChannelAndAssert( - t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ - Amt: chanAmt, - PushAmt: pushAmt, - }, - ) - networkChans = append(networkChans, chanPointAlice) - - aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAlice) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - aliceFundPoint := wire.OutPoint{ - Hash: *aliceChanTXID, - Index: chanPointAlice.OutputIndex, - } - - // As preliminary setup, we'll create two new nodes: Carol and Dave, - // such that we now have a 4 ndoe, 3 channel topology. Dave will make - // a channel with Alice, and Carol with Dave. After this setup, the - // network topology should now look like: - // Carol -> Dave -> Alice -> Bob - // - // First, we'll create Dave and establish a channel to Alice. - dave := net.NewNode(t.t, "Dave", nil) - defer shutdownAndAssert(net, t, dave) - - net.ConnectNodes(t.t, dave, net.Alice) - net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, dave) - - chanPointDave := openChannelAndAssert( - t, net, dave, net.Alice, - lntest.OpenChannelParams{ - Amt: chanAmt, - PushAmt: pushAmt, - }, - ) - - networkChans = append(networkChans, chanPointDave) - daveChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointDave) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - daveFundPoint := wire.OutPoint{ - Hash: *daveChanTXID, - Index: chanPointDave.OutputIndex, - } - - // Next, we'll create Carol and establish a channel to from her to - // Dave. Carol is started in htlchodl mode so that we can disconnect the - // intermediary hops before starting the settle. - carol := net.NewNode(t.t, "Carol", []string{"--hodl.exit-settle"}) - defer shutdownAndAssert(net, t, carol) - - net.ConnectNodes(t.t, carol, dave) - net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, carol) - - chanPointCarol := openChannelAndAssert( - t, net, carol, dave, - lntest.OpenChannelParams{ - Amt: chanAmt, - PushAmt: pushAmt, - }, - ) - networkChans = append(networkChans, chanPointCarol) - - carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - carolFundPoint := wire.OutPoint{ - Hash: *carolChanTXID, - Index: chanPointCarol.OutputIndex, - } - - // Wait for all nodes to have seen all channels. - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} - nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} - for _, chanPoint := range networkChans { - for i, node := range nodes { - txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - point := wire.OutPoint{ - Hash: *txid, - Index: chanPoint.OutputIndex, - } - - err = node.WaitForNetworkChannelOpen(chanPoint) - if err != nil { - t.Fatalf("%s(%d): timeout waiting for "+ - "channel(%s) open: %v", nodeNames[i], - node.NodeID, point, err) - } - } - } - - // Create 5 invoices for Carol, which expect a payment from Bob for 1k - // satoshis with a different preimage each time. - const numPayments = 5 - const paymentAmt = 1000 - payReqs, _, _, err := createPayReqs( - carol, paymentAmt, numPayments, - ) - if err != nil { - t.Fatalf("unable to create pay reqs: %v", err) - } - - // We'll wait for all parties to recognize the new channels within the - // network. - err = dave.WaitForNetworkChannelOpen(chanPointDave) - if err != nil { - t.Fatalf("dave didn't advertise his channel: %v", err) - } - err = carol.WaitForNetworkChannelOpen(chanPointCarol) - if err != nil { - t.Fatalf("carol didn't advertise her channel in time: %v", - err) - } - - // Using Carol as the source, pay to the 5 invoices from Bob created - // above. - err = completePaymentRequests( - net.Bob, net.Bob.RouterClient, payReqs, false, - ) - if err != nil { - t.Fatalf("unable to send payments: %v", err) - } - - var predErr error - err = wait.Predicate(func() bool { - predErr = assertNumActiveHtlcs(nodes, numPayments) - return predErr == nil - }, defaultTimeout) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } +func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) { + // Setup our test scenario. We should now have four nodes running with + // three channels. + s := setupScenarioFourNodes(ht) + defer s.cleanUp() // Disconnect the two intermediaries, Alice and Dave, by shutting down // Alice. - if err := net.StopNode(net.Alice); err != nil { - t.Fatalf("unable to shutdown alice: %v", err) - } + restartAlice := ht.SuspendNode(s.alice) // Now restart carol without hodl mode, to settle back the outstanding // payments. - carol.SetExtraArgs(nil) - if err := net.RestartNode(carol, nil); err != nil { - t.Fatalf("Node restart failed: %v", err) - } + s.carol.SetExtraArgs(nil) + ht.RestartNode(s.carol) // Make Carol and Dave are reconnected before waiting for the htlcs to // clear. - net.EnsureConnected(t.t, dave, carol) + ht.EnsureConnected(s.dave, s.carol) - // Wait for Carol to report no outstanding htlcs, and also for Dav to + // Wait for Carol to report no outstanding htlcs, and also for Dave to // receive all the settles from Carol. - carolNode := []*lntest.HarnessNode{carol} - err = wait.Predicate(func() bool { - predErr = assertNumActiveHtlcs(carolNode, 0) - if predErr != nil { - return false - } - - predErr = assertNumActiveHtlcsChanPoint(dave, carolFundPoint, 0) - return predErr == nil - }, defaultTimeout) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } + ht.AssertNumActiveHtlcs(s.carol, 0) + // As an intermediate node, Dave should now have zero outgoing HTLCs + // and 5 incoming HTLCs from Alice. + ht.AssertNumActiveHtlcs(s.dave, numPayments) // Finally, restart dave who received the settles, but was unable to // deliver them to Alice since they were disconnected. - if err := net.RestartNode(dave, nil); err != nil { - t.Fatalf("unable to restart dave: %v", err) - } - if err = net.RestartNode(net.Alice, nil); err != nil { - t.Fatalf("unable to restart alice: %v", err) - } + ht.RestartNode(s.dave) + require.NoError(ht, restartAlice(), "restart alice failed") // Force Dave and Alice to reconnect before waiting for the htlcs to // clear. - net.EnsureConnected(t.t, dave, net.Alice) + ht.EnsureConnected(s.dave, s.alice) // After reconnection succeeds, the settles should be propagated all // the way back to the sender. All nodes should report no active htlcs. - err = wait.Predicate(func() bool { - return assertNumActiveHtlcs(nodes, 0) == nil - }, defaultTimeout) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } + s.assertHTLCs(ht, 0) // When asserting the amount of satoshis moved, we'll factor in the // default base fee, as we didn't modify the fee structure when // creating the seed nodes in the network. - const baseFee = 1 // At this point all the channels within our proto network should be // shifted by 5k satoshis in the direction of Carol, the sink within the @@ -394,18 +227,7 @@ func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harness // transaction, in channel Bob->Alice->David->Carol, order is Carol, // David, Alice, Bob. var amountPaid = int64(5000) - assertAmountPaid(t, "Dave(local) => Carol(remote)", carol, - carolFundPoint, int64(0), amountPaid) - assertAmountPaid(t, "Dave(local) => Carol(remote)", dave, - carolFundPoint, amountPaid, int64(0)) - assertAmountPaid(t, "Alice(local) => Dave(remote)", dave, - daveFundPoint, int64(0), amountPaid+(baseFee*numPayments)) - assertAmountPaid(t, "Alice(local) => Dave(remote)", net.Alice, - daveFundPoint, amountPaid+(baseFee*numPayments), int64(0)) - assertAmountPaid(t, "Bob(local) => Alice(remote)", net.Alice, - aliceFundPoint, int64(0), amountPaid+((baseFee*numPayments)*2)) - assertAmountPaid(t, "Bob(local) => Alice(remote)", net.Bob, - aliceFundPoint, amountPaid+(baseFee*numPayments)*2, int64(0)) + s.assertAmoutPaid(ht, amountPaid, numPayments) // Lastly, we will send one more payment to ensure all channels are // still functioning properly. @@ -413,44 +235,19 @@ func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harness Memo: "testing", Value: paymentAmt, } - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - resp, err := carol.AddInvoice(ctxt, finalInvoice) - if err != nil { - t.Fatalf("unable to add invoice: %v", err) - } - - payReqs = []string{resp.PaymentRequest} + resp := s.carol.RPC.AddInvoice(finalInvoice) + payReqs := []string{resp.PaymentRequest} // Before completing the final payment request, ensure that the // connection between Dave and Carol has been healed. - net.EnsureConnected(t.t, dave, carol) + ht.EnsureConnected(s.dave, s.carol) // Using Carol as the source, pay to the 5 invoices from Bob created // above. - err = completePaymentRequests( - net.Bob, net.Bob.RouterClient, payReqs, true, - ) - if err != nil { - t.Fatalf("unable to send payments: %v", err) - } + ht.CompletePaymentRequests(s.bob, payReqs) amountPaid = int64(6000) - assertAmountPaid(t, "Dave(local) => Carol(remote)", carol, - carolFundPoint, int64(0), amountPaid) - assertAmountPaid(t, "Dave(local) => Carol(remote)", dave, - carolFundPoint, amountPaid, int64(0)) - assertAmountPaid(t, "Alice(local) => Dave(remote)", dave, - daveFundPoint, int64(0), amountPaid+(baseFee*(numPayments+1))) - assertAmountPaid(t, "Alice(local) => Dave(remote)", net.Alice, - daveFundPoint, amountPaid+(baseFee*(numPayments+1)), int64(0)) - assertAmountPaid(t, "Bob(local) => Alice(remote)", net.Alice, - aliceFundPoint, int64(0), amountPaid+((baseFee*(numPayments+1))*2)) - assertAmountPaid(t, "Bob(local) => Alice(remote)", net.Bob, - aliceFundPoint, amountPaid+(baseFee*(numPayments+1))*2, int64(0)) - - closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) - closeChannelAndAssert(t, net, dave, chanPointDave, false) - closeChannelAndAssert(t, net, carol, chanPointCarol, false) + s.assertAmoutPaid(ht, amountPaid, numPayments+1) } // testSwitchOfflineDeliveryOutgoingOffline constructs a set of multihop payments, diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index 91441307d..8207da236 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -28,10 +28,6 @@ var allTestCases = []*testCase{ name: "async bidirectional payments", test: testBidirectionalAsyncPayments, }, - { - name: "switch offline delivery persistence", - test: testSwitchOfflineDeliveryPersistence, - }, { name: "switch offline delivery outgoing offline", test: testSwitchOfflineDeliveryOutgoingOffline,