From 4dcce9df6944efb5f894733a60ed84a37708808b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 16 Jul 2024 01:53:59 +0800 Subject: [PATCH] lntest+itest: fix flakes found using `neutrino` backend This commit makes sure the sweep requests are received before mining blocks to trigger the actual sweeping. In addition, `testFundingExpiryBlocksOnPending` is updated to deal with the old `channel link not found` issue. --- itest/lnd_funding_test.go | 18 ++++++++++-------- itest/lnd_open_channel_test.go | 13 +++++++++++++ itest/lnd_psbt_test.go | 14 ++++++-------- lntest/harness_assertion.go | 7 ++++++- lntest/utils.go | 10 ++++++++-- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/itest/lnd_funding_test.go b/itest/lnd_funding_test.go index f8ba4f9fb4..c6c79a893c 100644 --- a/itest/lnd_funding_test.go +++ b/itest/lnd_funding_test.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainreg" - "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" @@ -1341,22 +1340,22 @@ func testChannelFundingWithUnstableUtxos(ht *lntest.HarnessTest) { // that by dave force-closing the channel. Which let's carol sweep its // to_remote output which is not encumbered by any relative locktime. ht.CloseChannelAssertPending(dave, chanPoint2, true) + // Mine the force close commitment transaction. ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) // We need to wait for carol initiating the sweep of the to_remote // output of chanPoint2. - utxos := ht.AssertNumUTXOsUnconfirmed(carol, 1) + utxo := ht.AssertNumUTXOsUnconfirmed(carol, 1)[0] - // We filter for the unconfirmed utxo and try to open a channel with - // that utxo. - utxoOpt := fn.Find(func(u *lnrpc.Utxo) bool { - return u.Confirmations == 0 - }, utxos) - fundingUtxo := utxoOpt.UnwrapOrFail(ht.T) + // We now try to open channel using the unconfirmed utxo. + fundingUtxo := utxo // Now try to open the channel with this utxo and expect an error. expectedErr := fmt.Errorf("outpoint already spent or "+ @@ -1405,6 +1404,9 @@ func testChannelFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, chanPoint3, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) diff --git a/itest/lnd_open_channel_test.go b/itest/lnd_open_channel_test.go index a7bac1b451..52ec622cf7 100644 --- a/itest/lnd_open_channel_test.go +++ b/itest/lnd_open_channel_test.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" "testing" + "time" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -767,6 +768,18 @@ func testFundingExpiryBlocksOnPending(ht *lntest.HarnessTest) { // channel. ht.MineBlocksAndAssertNumTxes(1, 1) chanPoint := lntest.ChanPointFromPendingUpdate(update) + + // TODO(yy): remove the sleep once the following bug is fixed. + // + // We may get the error `unable to gracefully close channel + // while peer is offline (try force closing it instead): + // channel link not found`. This happens because the channel + // link hasn't been added yet but we now proceed to closing the + // channel. We may need to revisit how the channel open event + // is created and make sure the event is only sent after all + // relevant states have been updated. + time.Sleep(2 * time.Second) + ht.CloseChannel(alice, chanPoint) } diff --git a/itest/lnd_psbt_test.go b/itest/lnd_psbt_test.go index 9ed7295243..91d67ba376 100644 --- a/itest/lnd_psbt_test.go +++ b/itest/lnd_psbt_test.go @@ -1683,6 +1683,9 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, channelPoint, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) @@ -1805,6 +1808,9 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, channelPoint2, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) @@ -1929,12 +1935,6 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { updateResp = ht.ReceiveOpenChannelUpdate(chanUpdates) upd, ok = updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) require.True(ht, ok) - channelPoint3 := &lnrpc.ChannelPoint{ - FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ - FundingTxidBytes: upd.ChanPending.Txid, - }, - OutputIndex: upd.ChanPending.OutputIndex, - } err = finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx)) require.NoError(ht, err) @@ -1942,6 +1942,4 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { txHash = finalTx.TxHash() block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] ht.AssertTxInBlock(block, &txHash) - - ht.CloseChannel(carol, channelPoint3) } diff --git a/lntest/harness_assertion.go b/lntest/harness_assertion.go index 7a863a028e..4a5d04274e 100644 --- a/lntest/harness_assertion.go +++ b/lntest/harness_assertion.go @@ -785,8 +785,13 @@ func (h *HarnessTest) AssertNumUTXOsWithConf(hn *node.HarnessNode, return nil } + desc := "has UTXOs:\n" + for _, utxo := range resp.Utxos { + desc += fmt.Sprintf("%v\n", utxo) + } + return errNumNotMatched(hn.Name(), "num of UTXOs", - expectedUtxos, total-old, total, old) + expectedUtxos, total-old, total, old, desc) }, DefaultTimeout) require.NoError(h, err, "timeout waiting for UTXOs") diff --git a/lntest/utils.go b/lntest/utils.go index d230b6b611..d4ca705c31 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -53,10 +53,16 @@ func CopyFile(dest, src string) error { // errNumNotMatched is a helper method to return a nicely formatted error. func errNumNotMatched(name string, subject string, - want, got, total, old int) error { + want, got, total, old int, desc ...any) error { - return fmt.Errorf("%s: assert %s failed: want %d, got: %d, total: "+ + err := fmt.Errorf("%s: assert %s failed: want %d, got: %d, total: "+ "%d, previously had: %d", name, subject, want, got, total, old) + + if len(desc) > 0 { + err = fmt.Errorf("%w, desc: %v", err, desc) + } + + return err } // parseDerivationPath parses a path in the form of m/x'/y'/z'/a/b into a slice