lntemp+itest: refactor testCPFP

This commit is contained in:
yyforyongyu committed 2023-01-18 10:53:56 +08:00
1 parent 08dfebbd6c
commit 309ba1fcf4
3 files changed
+39 -91

No files matched your search

+4
View File
@@ -453,4 +453,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
Name: "sign verify message", Name: "sign verify message",
TestFunc: testSignVerifyMessage, TestFunc: testSignVerifyMessage,
}, },
{
Name: "cpfp",
TestFunc: testCPFP,
},
} }
+35 -87
View File
@@ -2,7 +2,6 @@ package itest
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
@@ -14,7 +13,6 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp" "github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node" "github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/sweep" "github.com/lightningnetwork/lnd/sweep"
@@ -80,35 +78,28 @@ func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction. // rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
// //
// TODO(wilmer): Add RBF case once btcd supports it. // TODO(wilmer): Add RBF case once btcd supports it.
func testCPFP(net *lntest.NetworkHarness, t *harnessTest) { func testCPFP(ht *lntemp.HarnessTest) {
runCPFP(net, t, net.Alice, net.Bob) runCPFP(ht, ht.Alice, ht.Bob)
} }
// runCPFP ensures that the daemon can bump an unconfirmed transaction's fee // runCPFP ensures that the daemon can bump an unconfirmed transaction's fee
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction. // rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
func runCPFP(net *lntest.NetworkHarness, t *harnessTest, func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
alice, bob *lntest.HarnessNode) {
// Skip this test for neutrino, as it's not aware of mempool // Skip this test for neutrino, as it's not aware of mempool
// transactions. // transactions.
if net.BackendCfg.Name() == lntest.NeutrinoBackendName { if ht.IsNeutrinoBackend() {
t.Skipf("skipping CPFP test for neutrino backend") ht.Skipf("skipping CPFP test for neutrino backend")
} }
// We'll start the test by sending Alice some coins, which she'll use to // We'll start the test by sending Alice some coins, which she'll use
// send to Bob. // to send to Bob.
ctxb := context.Background() ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, alice)
// Create an address for Bob to send the coins to. // Create an address for Bob to send the coins to.
addrReq := &lnrpc.NewAddressRequest{ req := &lnrpc.NewAddressRequest{
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH, Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
} }
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) resp := bob.RPC.NewAddress(req)
resp, err := bob.NewAddress(ctxt, addrReq)
if err != nil {
t.Fatalf("unable to get new address for bob: %v", err)
}
// Send the coins from Alice to Bob. We should expect a transaction to // Send the coins from Alice to Bob. We should expect a transaction to
// be broadcast and seen in the mempool. // be broadcast and seen in the mempool.
@@ -116,46 +107,33 @@ func runCPFP(net *lntest.NetworkHarness, t *harnessTest,
Addr: resp.Address, Addr: resp.Address,
Amount: btcutil.SatoshiPerBitcoin, Amount: btcutil.SatoshiPerBitcoin,
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) alice.RPC.SendCoins(sendReq)
if _, err = alice.SendCoins(ctxt, sendReq); err != nil { txid := ht.Miner.AssertNumTxsInMempool(1)[0]
t.Fatalf("unable to send coins to bob: %v", err)
}
txid, err := waitForTxInMempool(net.Miner.Client, minerMempoolTimeout)
if err != nil {
t.Fatalf("expected one mempool transaction: %v", err)
}
// We'll then extract the raw transaction from the mempool in order to // We'll then extract the raw transaction from the mempool in order to
// determine the index of Bob's output. // determine the index of Bob's output.
tx, err := net.Miner.Client.GetRawTransaction(txid) tx := ht.Miner.GetRawTransaction(txid)
if err != nil {
t.Fatalf("unable to extract raw transaction from mempool: %v",
err)
}
bobOutputIdx := -1 bobOutputIdx := -1
for i, txOut := range tx.MsgTx().TxOut { for i, txOut := range tx.MsgTx().TxOut {
_, addrs, _, err := txscript.ExtractPkScriptAddrs( _, addrs, _, err := txscript.ExtractPkScriptAddrs(
txOut.PkScript, net.Miner.ActiveNet, txOut.PkScript, ht.Miner.ActiveNet,
) )
if err != nil { require.NoErrorf(ht, err, "unable to extract address "+
t.Fatalf("unable to extract address from pkScript=%x: "+ "from pkScript=%x: %v", txOut.PkScript, err)
"%v", txOut.PkScript, err)
}
if addrs[0].String() == resp.Address { if addrs[0].String() == resp.Address {
bobOutputIdx = i bobOutputIdx = i
} }
} }
if bobOutputIdx == -1 { require.NotEqual(ht, -1, bobOutputIdx, "bob's output was not found "+
t.Fatalf("bob's output was not found within the transaction") "within the transaction")
}
// Wait until bob has seen the tx and considers it as owned. // Wait until bob has seen the tx and considers it as owned.
op := &lnrpc.OutPoint{ op := &lnrpc.OutPoint{
TxidBytes: txid[:], TxidBytes: txid[:],
OutputIndex: uint32(bobOutputIdx), OutputIndex: uint32(bobOutputIdx),
} }
assertWalletUnspent(t, bob, op, "") ht.AssertUTXOInWallet(bob, op, "")
// We'll attempt to bump the fee of this transaction by performing a // We'll attempt to bump the fee of this transaction by performing a
// CPFP from Alice's point of view. // CPFP from Alice's point of view.
@@ -165,68 +143,38 @@ func runCPFP(net *lntest.NetworkHarness, t *harnessTest,
sweep.DefaultMaxFeeRate.FeePerKVByte() / 2000, sweep.DefaultMaxFeeRate.FeePerKVByte() / 2000,
), ),
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) bob.RPC.BumpFee(bumpFeeReq)
_, err = bob.WalletKitClient.BumpFee(ctxt, bumpFeeReq)
if err != nil {
t.Fatalf("unable to bump fee: %v", err)
}
// We should now expect to see two transactions within the mempool, a // We should now expect to see two transactions within the mempool, a
// parent and its child. // parent and its child.
_, err = waitForNTxsInMempool(net.Miner.Client, 2, minerMempoolTimeout) ht.Miner.AssertNumTxsInMempool(2)
if err != nil {
t.Fatalf("expected two mempool transactions: %v", err)
}
// We should also expect to see the output being swept by the // We should also expect to see the output being swept by the
// UtxoSweeper. We'll ensure it's using the fee rate specified. // UtxoSweeper. We'll ensure it's using the fee rate specified.
pendingSweepsReq := &walletrpc.PendingSweepsRequest{} pendingSweepsResp := bob.RPC.PendingSweeps()
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) require.Len(ht, pendingSweepsResp.PendingSweeps, 1,
pendingSweepsResp, err := bob.WalletKitClient.PendingSweeps( "expected to find 1 pending sweep")
ctxt, pendingSweepsReq,
)
if err != nil {
t.Fatalf("unable to retrieve pending sweeps: %v", err)
}
if len(pendingSweepsResp.PendingSweeps) != 1 {
t.Fatalf("expected to find %v pending sweep(s), found %v", 1,
len(pendingSweepsResp.PendingSweeps))
}
pendingSweep := pendingSweepsResp.PendingSweeps[0] pendingSweep := pendingSweepsResp.PendingSweeps[0]
if !bytes.Equal(pendingSweep.Outpoint.TxidBytes, op.TxidBytes) { require.Equal(ht, pendingSweep.Outpoint.TxidBytes, op.TxidBytes,
t.Fatalf("expected output txid %x, got %x", op.TxidBytes, "output txid not matched")
pendingSweep.Outpoint.TxidBytes) require.Equal(ht, pendingSweep.Outpoint.OutputIndex, op.OutputIndex,
} "output index not matched")
if pendingSweep.Outpoint.OutputIndex != op.OutputIndex { require.Equal(ht, pendingSweep.SatPerVbyte, bumpFeeReq.SatPerVbyte,
t.Fatalf("expected output index %v, got %v", op.OutputIndex, "sweep sat per vbyte not matched")
pendingSweep.Outpoint.OutputIndex)
}
if pendingSweep.SatPerVbyte != bumpFeeReq.SatPerVbyte {
t.Fatalf("expected sweep sat per vbyte %v, got %v",
bumpFeeReq.SatPerVbyte, pendingSweep.SatPerVbyte)
}
// Mine a block to clean up the unconfirmed transactions. // Mine a block to clean up the unconfirmed transactions.
mineBlocks(t, net, 1, 2) ht.MineBlocksAndAssertNumTxes(1, 2)
// The input used to CPFP should no longer be pending. // The input used to CPFP should no longer be pending.
err = wait.NoError(func() error { err := wait.NoError(func() error {
req := &walletrpc.PendingSweepsRequest{} resp := bob.RPC.PendingSweeps()
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
resp, err := bob.WalletKitClient.PendingSweeps(ctxt, req)
if err != nil {
return fmt.Errorf("unable to retrieve bob's pending "+
"sweeps: %v", err)
}
if len(resp.PendingSweeps) != 0 { if len(resp.PendingSweeps) != 0 {
return fmt.Errorf("expected 0 pending sweeps, found %d", return fmt.Errorf("expected 0 pending sweeps, found %d",
len(resp.PendingSweeps)) len(resp.PendingSweeps))
} }
return nil return nil
}, defaultTimeout) }, defaultTimeout)
if err != nil { require.NoError(ht, err, "timeout checking bob's pending sweeps")
t.Fatalf(err.Error())
}
} }
// testAnchorReservedValue tests that we won't allow sending transactions when // testAnchorReservedValue tests that we won't allow sending transactions when
-4
View File
@@ -12,10 +12,6 @@ var allTestCases = []*testCase{
name: "async bidirectional payments", name: "async bidirectional payments",
test: testBidirectionalAsyncPayments, test: testBidirectionalAsyncPayments,
}, },
{
name: "cpfp",
test: testCPFP,
},
{ {
name: "psbt channel funding", name: "psbt channel funding",
test: testPsbtChanFunding, test: testPsbtChanFunding,