From 0e73d2d243ed7fdb95befc23062b5d35f56d4d11 Mon Sep 17 00:00:00 2001 From: Matheus Degiovani Date: Wed, 8 Apr 2020 09:44:31 -0300 Subject: [PATCH] itest: assert unspent before performing CPFP This reduces the flakiness of the CPFP test by asserting the wallet has seen the unspent output before attempting to perform the walletkit's BumpFee method. Previously the attempt to bump the fee of the target transaction could be made before the wallet had had a chance to fully process the transaction, causing a flaky error. --- lnrpc/walletrpc/walletkit_server.go | 2 ++ lntest/itest/lnd_test.go | 33 +++++++++++++++++++++++++++++ lntest/itest/onchain.go | 7 ++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index a52bb9204..d93dd04e7 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -678,6 +678,8 @@ func (w *WalletKit) BumpFee(ctx context.Context, return nil, err } + log.Debugf("Attempting to CPFP outpoint %s", op) + // Since we're unable to perform a bump through RBF, we'll assume the // user is attempting to bump an unconfirmed transaction's fee rate by // sweeping an output within it under control of the wallet with a diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 16fdd0b35..380596e5d 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -155,6 +155,39 @@ func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash) t.Fatalf("tx was not included in block") } +func assertWalletUnspent(t *harnessTest, node *lntest.HarnessNode, out *lnrpc.OutPoint) { + t.t.Helper() + + err := wait.NoError(func() error { + ctxt, cancel := context.WithTimeout(context.Background(), defaultTimeout) + defer cancel() + unspent, err := node.ListUnspent(ctxt, &lnrpc.ListUnspentRequest{}) + if err != nil { + return err + } + + err = errors.New("tx with wanted txhash never found") + for _, utxo := range unspent.Utxos { + if !bytes.Equal(utxo.Outpoint.TxidBytes, out.TxidBytes) { + continue + } + + err = errors.New("wanted output is not a wallet utxo") + if utxo.Outpoint.OutputIndex != out.OutputIndex { + continue + } + + return nil + } + + return err + }, defaultTimeout) + if err != nil { + t.Fatalf("outpoint %s not unspent by %s's wallet: %v", out, + node.Name(), err) + } +} + func rpcPointToWirePoint(t *harnessTest, chanPoint *lnrpc.ChannelPoint) wire.OutPoint { txid, err := lnd.GetChanPointFundingTxid(chanPoint) if err != nil { diff --git a/lntest/itest/onchain.go b/lntest/itest/onchain.go index 22b50e3c5..7cc4df11e 100644 --- a/lntest/itest/onchain.go +++ b/lntest/itest/onchain.go @@ -86,12 +86,15 @@ func testCPFP(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("bob's output was not found within the transaction") } - // We'll attempt to bump the fee of this transaction by performing a - // CPFP from Alice's point of view. + // Wait until bob has seen the tx and considers it as owned. op := &lnrpc.OutPoint{ TxidBytes: txid[:], OutputIndex: uint32(bobOutputIdx), } + assertWalletUnspent(t, net.Bob, op) + + // We'll attempt to bump the fee of this transaction by performing a + // CPFP from Alice's point of view. bumpFeeReq := &walletrpc.BumpFeeRequest{ Outpoint: op, SatPerByte: uint32(sweep.DefaultMaxFeeRate.FeePerKVByte() / 2000),