diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index a52bb920..d93dd04e 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 16fdd0b3..380596e5 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 22b50e3c..7cc4df11 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),