package itest import ( "time" "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/stretchr/testify/require" ) // testWipeForwardingPackagesLocal tests that when a channel is closed, either // through local force close, remote close, or coop close, all the forwarding // packages of that particular channel are deleted. The test creates a // topology as Alice -> Bob -> Carol, and sends payments from Alice to Carol // through Bob. It then performs the test in two steps, // - Bob force closes the channel Alice->Bob, and checks from both Bob's // PoV(local force close) and Alice's Pov(remote close) that the forwarding // packages are wiped. // - Bob coop closes the channel Bob->Carol, and checks from both Bob PoVs // that the forwarding packages are wiped. func testWipeForwardingPackages(ht *lntest.HarnessTest) { const ( chanAmt = 10e6 paymentAmt = 10e4 finalCTLVDelta = chainreg.DefaultBitcoinTimeLockDelta numInvoices = 3 ) // Grab Alice and Bob from HarnessTest. alice, bob := ht.Alice, ht.Bob // Create a new node Carol, which will create invoices that require // Alice to pay. carol := ht.NewNode("Carol", nil) // Connect Bob to Carol. ht.ConnectNodes(bob, carol) // Open a channel between Alice and Bob. chanPointAB := ht.OpenChannel( alice, bob, lntest.OpenChannelParams{Amt: chanAmt}, ) // Open a channel between Bob and Carol. chanPointBC := ht.OpenChannel( bob, carol, lntest.OpenChannelParams{Amt: chanAmt}, ) // Before we continue, make sure Alice has seen the channel between Bob // and Carol. ht.AssertTopologyChannelOpen(alice, chanPointBC) // Alice sends several payments to Carol through Bob, which triggers // Bob to create forwarding packages. for i := 0; i < numInvoices; i++ { // Add an invoice for Carol. invoice := &lnrpc.Invoice{Memo: "testing", Value: paymentAmt} resp := carol.RPC.AddInvoice(invoice) // Alice sends a payment to Carol through Bob. ht.CompletePaymentRequests(alice, []string{resp.PaymentRequest}) } // TODO(yy): remove the sleep once the following bug is fixed. // When the invoice is reported settled, the commitment dance is not // yet finished, which can cause an error when closing the channel, // saying there's active HTLCs. We need to investigate this issue and // reverse the order to, first finish the commitment dance, then report // the invoice as settled. time.Sleep(2 * time.Second) // Firstly, Bob force closes the channel. ht.CloseChannelAssertPending(bob, chanPointAB, true) // Now that the channel has been force closed, it should show up in // bob's PendingChannels RPC under the waiting close section. pendingAB := ht.AssertChannelWaitingClose(bob, chanPointAB).Channel // Check that Bob has created forwarding packages. We don't care the // exact number here as long as these packages are deleted when the // channel is closed. require.NotZero(ht, pendingAB.NumForwardingPackages) // Secondly, Bob coop closes the channel. ht.CloseChannelAssertPending(bob, chanPointBC, false) // Now that the channel has been coop closed, it should show up in // bob's PendingChannels RPC under the waiting close section. pendingBC := ht.AssertChannelWaitingClose(bob, chanPointBC).Channel // Check that Bob has created forwarding packages. We don't care the // exact number here as long as these packages are deleted when the // channel is closed. require.NotZero(ht, pendingBC.NumForwardingPackages) // Since it's a coop close, Carol should see the waiting close channel // too. pendingBC = ht.AssertChannelWaitingClose(carol, chanPointBC).Channel require.NotZero(ht, pendingBC.NumForwardingPackages) // Mine 1 block to get the two closing transactions confirmed. ht.MineBlocksAndAssertNumTxes(1, 2) // Now that the closing transaction is confirmed, the above waiting // close channel should now become pending force closed channel. pendingAB = ht.AssertChannelPendingForceClose(bob, chanPointAB).Channel // Check the forwarding pacakges are deleted. require.Zero(ht, pendingAB.NumForwardingPackages) // For Alice, the forwarding packages should have been wiped too. pending := ht.AssertChannelPendingForceClose(alice, chanPointAB) pendingAB = pending.Channel require.Zero(ht, pendingAB.NumForwardingPackages) // Alice should one pending sweep. ht.AssertNumPendingSweeps(alice, 1) // Mine a block to trigger the sweep. ht.MineBlocks(1) // Mine 1 block to get Alice's sweeping tx confirmed. ht.MineBlocksAndAssertNumTxes(1, 1) // Clean up the force closed channel. ht.CleanupForceClose(bob) }