From 187e61da23ec502284df6c8e59e7badca9339556 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Thu, 1 Feb 2024 20:47:10 +0100 Subject: [PATCH] itests: add itest for ListSweeps's start_height --- itest/list_on_test.go | 4 ++ itest/lnd_channel_force_close_test.go | 4 +- itest/lnd_onchain_test.go | 97 +++++++++++++++++++++++++++ lntest/harness.go | 4 +- lntest/rpc/wallet_kit.go | 9 ++- 5 files changed, 112 insertions(+), 6 deletions(-) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 9e735dcff..390e9a49e 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -562,6 +562,10 @@ var allTestCases = []*lntest.TestCase{ Name: "removetx", TestFunc: testRemoveTx, }, + { + Name: "listsweeps", + TestFunc: testListSweeps, + }, { Name: "fail funding flow psbt", TestFunc: testPsbtChanFundingFailFlow, diff --git a/itest/lnd_channel_force_close_test.go b/itest/lnd_channel_force_close_test.go index 0a0c4d0a6..b0aba4c07 100644 --- a/itest/lnd_channel_force_close_test.go +++ b/itest/lnd_channel_force_close_test.go @@ -661,7 +661,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Check that we can find the commitment sweep in our set of known // sweeps, using the simple transaction id ListSweeps output. - ht.AssertSweepFound(alice, sweepingTXID.String(), false) + ht.AssertSweepFound(alice, sweepingTXID.String(), false, 0) // Restart Alice to ensure that she resumes watching the finalized // commitment sweep txid. @@ -989,7 +989,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Check that we can find the htlc sweep in our set of sweeps using // the verbose output of the listsweeps output. - ht.AssertSweepFound(alice, htlcSweepTx.Hash().String(), true) + ht.AssertSweepFound(alice, htlcSweepTx.Hash().String(), true, 0) // The following restart checks to ensure that the nursery store is // storing the txid of the previously broadcast htlc sweep txn, and that diff --git a/itest/lnd_onchain_test.go b/itest/lnd_onchain_test.go index 6068832e0..5b8080387 100644 --- a/itest/lnd_onchain_test.go +++ b/itest/lnd_onchain_test.go @@ -832,3 +832,100 @@ func testRemoveTx(ht *lntest.HarnessTest) { expectedAmt = btcutil.Amount(initialWalletAmt) - txFee require.EqualValues(ht, expectedAmt, aliceBalResp.ConfirmedBalance) } + +// testListSweeps tests that we are able to: +// - list only those sweeps that are currently in the mempool, +// - list sweeps given a starting block height, +// - list all sweeps. +func testListSweeps(ht *lntest.HarnessTest) { + // Skip this test for neutrino, as it's not aware of mempool + // transactions. + if ht.IsNeutrinoBackend() { + ht.Skipf("skipping ListSweeps test for neutrino backend") + } + + // Create nodes so that we start with no funds on the internal wallet. + alice := ht.NewNode("Alice", nil) + bob := ht.NewNode("Bob", nil) + + const initialWalletAmt = btcutil.SatoshiPerBitcoin + + // Fund Alice with an initial balance. + ht.FundCoins(initialWalletAmt, alice) + + // Connect Alice to Bob. + ht.ConnectNodes(alice, bob) + + // Open a few channels between Alice and Bob. + var chanPoints []*lnrpc.ChannelPoint + for i := 0; i < 3; i++ { + chanPoint := ht.OpenChannel( + alice, bob, lntest.OpenChannelParams{ + Amt: 1e6, + PushAmt: 5e5, + }, + ) + + chanPoints = append(chanPoints, chanPoint) + } + + ht.Shutdown(bob) + + // Close the first channel and sweep the funds. + ht.ForceCloseChannel(alice, chanPoints[0]) + + // Jump a block. + ht.MineBlocks(1) + + // Get the current block height. + bestBlockRes := ht.Alice.RPC.GetBestBlock(nil) + blockHeight := bestBlockRes.BlockHeight + + // Close the second channel and also sweep the funds. + ht.ForceCloseChannel(alice, chanPoints[1]) + + // Now close the third channel but don't sweep the funds just yet. + closeStream, _ := ht.CloseChannelAssertPending( + alice, chanPoints[2], true, + ) + + ht.AssertStreamChannelForceClosed( + alice, chanPoints[2], false, closeStream, + ) + + // Mine enough blocks for the node to sweep its funds from the force + // closed channel. The commit sweep resolver is able to broadcast the + // sweep tx up to one block before the CSV elapses, so wait until + // defaulCSV-1. + ht.MineEmptyBlocks(node.DefaultCSV - 1) + + // Now we can expect that the sweep has been broadcast. + pendingTxHash := ht.Miner.AssertNumTxsInMempool(1) + + // List all unconfirmed sweeps that alice's node had broadcast. + sweepResp := alice.RPC.ListSweeps(false, -1) + txIDs := sweepResp.GetTransactionIds().TransactionIds + + require.Lenf(ht, txIDs, 1, "number of pending sweeps, starting from "+ + "height -1") + require.Equal(ht, pendingTxHash[0].String(), txIDs[0]) + + // Now list sweeps from the closing of the first channel. We should + // only see the sweep from the second channel and the pending one. + sweepResp = alice.RPC.ListSweeps(false, blockHeight) + txIDs = sweepResp.GetTransactionIds().TransactionIds + require.Lenf(ht, txIDs, 2, "number of sweeps, starting from height %d", + blockHeight) + + // Finally list all sweeps from the closing of the second channel. We + // should see all sweeps, including the pending one. + sweepResp = alice.RPC.ListSweeps(false, 0) + txIDs = sweepResp.GetTransactionIds().TransactionIds + require.Lenf(ht, txIDs, 3, "number of sweeps, starting from height 0") + + // Mine the pending sweep and make sure it is no longer returned. + ht.MineBlocks(1) + sweepResp = alice.RPC.ListSweeps(false, -1) + txIDs = sweepResp.GetTransactionIds().TransactionIds + require.Empty(ht, txIDs, "pending sweep should not be returned") +} diff --git a/lntest/harness.go b/lntest/harness.go index 724d7ca5c..23f5a8b43 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -2041,10 +2041,10 @@ func (h *HarnessTest) FindCommitAndAnchor(sweepTxns []*wire.MsgTx, // // NOTE: Does not account for node's internal state. func (h *HarnessTest) AssertSweepFound(hn *node.HarnessNode, - sweep string, verbose bool) { + sweep string, verbose bool, startHeight int32) { // List all sweeps that alice's node had broadcast. - sweepResp := hn.RPC.ListSweeps(verbose) + sweepResp := hn.RPC.ListSweeps(verbose, startHeight) var found bool if verbose { diff --git a/lntest/rpc/wallet_kit.go b/lntest/rpc/wallet_kit.go index 2b403715f..79ccdcbdf 100644 --- a/lntest/rpc/wallet_kit.go +++ b/lntest/rpc/wallet_kit.go @@ -159,11 +159,16 @@ func (h *HarnessRPC) VerifyMessageWithAddr( } // ListSweeps makes a ListSweeps RPC call to the node's WalletKit client. -func (h *HarnessRPC) ListSweeps(verbose bool) *walletrpc.ListSweepsResponse { +func (h *HarnessRPC) ListSweeps(verbose bool, + startHeight int32) *walletrpc.ListSweepsResponse { + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) defer cancel() - req := &walletrpc.ListSweepsRequest{Verbose: verbose} + req := &walletrpc.ListSweepsRequest{ + Verbose: verbose, + StartHeight: startHeight, + } resp, err := h.WalletKit.ListSweeps(ctxt, req) h.NoError(err, "ListSweeps")