lntest: fix commitment TX not found in mempool error

This commit fixes an old flake in the neutrino anchor output tests. It
turns out that sometimes with Neutrino we don't have enough UTXOs in our
wallet to sweep both the local and remote anchor. This is very likely a
timing issue, we need to give the wallet more time to catch up with the
chain and process all transactions to find unspent outputs.
We address this two-fold: We add an additional UTXO to Alice. And then
we also make sure we detect both UTXOs properly after restarting.
This commit is contained in:
Oliver Gugger 2021-07-13 18:12:34 +02:00
parent 5cabd980b1
commit 3ae2cdb003
No known key found for this signature in database
GPG Key ID: 8E4256593F177720
3 changed files with 48 additions and 7 deletions

@ -772,7 +772,15 @@ func (n *NetworkHarness) RestartNode(node *HarnessNode, callback func() error,
unlockReq.RecoveryWindow = 1000
}
return node.Unlock(context.Background(), unlockReq)
if err := node.Unlock(context.Background(), unlockReq); err != nil {
return err
}
// Give the node some time to catch up with the chain before we continue
// with the tests.
ctxc, done := context.WithTimeout(context.Background(), DefaultTimeout)
defer done()
return node.WaitForBlockchainSync(ctxc)
}
// RestartNodeNoUnlock attempts to restart a lightning node by shutting it down

@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"io"
"math"
"sync/atomic"
"testing"
"time"
@ -1714,3 +1715,30 @@ func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) (
}
}
}
// assertNumUTXOs waits for the given number of UTXOs to be available or fails
// if that isn't the case before the default timeout.
func assertNumUTXOs(t *testing.T, node *lntest.HarnessNode, expectedUtxos int) {
ctxb := context.Background()
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
err := wait.NoError(func() error {
resp, err := node.ListUnspent( // nolint:staticcheck
ctxt, &lnrpc.ListUnspentRequest{
MinConfs: 1,
MaxConfs: math.MaxInt32,
},
)
if err != nil {
return fmt.Errorf("error listing unspent: %v", err)
}
if len(resp.Utxos) != expectedUtxos {
return fmt.Errorf("not enough UTXOs, got %d wanted %d",
len(resp.Utxos), expectedUtxos)
}
return nil
}, defaultTimeout)
require.NoError(t, err, "wait for listunspent")
}

@ -314,6 +314,9 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest,
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
net.ConnectNodes(ctxt, t.t, alice, carol)
// We need one additional UTXO for sweeping the remote anchor.
net.SendCoins(ctxt, t.t, btcutil.SatoshiPerBitcoin, alice)
// Before we start, obtain Carol's current wallet balance, we'll check
// to ensure that at the end of the force closure by Alice, Carol
// recognizes his new on-chain output.
@ -484,6 +487,12 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest,
t.Fatalf("Node restart failed: %v", err)
}
// To give the neutrino backend some time to catch up with the chain, we
// wait here until we have enough UTXOs to actually sweep the local and
// remote anchor.
const expectedUtxos = 2
assertNumUTXOs(t.t, alice, expectedUtxos)
// Mine a block which should confirm the commitment transaction
// broadcast as a result of the force closure. If there are anchors, we
// also expect the anchor sweep tx to be in the mempool.
@ -497,9 +506,7 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest,
sweepTxns, err := getNTxsFromMempool(
net.Miner.Client, expectedTxes, minerMempoolTimeout,
)
if err != nil {
t.Fatalf("failed to find commitment in miner mempool: %v", err)
}
require.NoError(t.t, err, "sweep txns in miner mempool")
// Verify fee rate of the commitment tx plus anchor if present.
var totalWeight, totalFee int64
@ -520,9 +527,7 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest,
// Find alice's commit sweep and anchor sweep (if present) in the
// mempool.
aliceCloseTx := waitingClose.Commitments.LocalTxid
_, aliceAnchor := findCommitAndAnchor(
t, net, sweepTxns, aliceCloseTx,
)
_, aliceAnchor := findCommitAndAnchor(t, net, sweepTxns, aliceCloseTx)
// If we expect anchors, add alice's anchor to our expected set of
// reports.