From 211dad1574e7f0ad1c71349754292c4e64f6a619 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sun, 7 Aug 2022 05:50:49 +0800 Subject: [PATCH] itest: refactor `testAnchorReservedValue` --- lntest/itest/list_on_test.go | 4 + lntest/itest/lnd_onchain_test.go | 179 ++++++++------------------ lntest/itest/lnd_test_list_on_test.go | 4 - 3 files changed, 55 insertions(+), 132 deletions(-) diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index 9005fd6df..2c1373c9c 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -263,4 +263,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "multi-hop payments", TestFunc: testMultiHopPayments, }, + { + Name: "anchors reserved value", + TestFunc: testAnchorReservedValue, + }, } diff --git a/lntest/itest/lnd_onchain_test.go b/lntest/itest/lnd_onchain_test.go index 4f94b7e0f..4444caa70 100644 --- a/lntest/itest/lnd_onchain_test.go +++ b/lntest/itest/lnd_onchain_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "strings" "time" "github.com/btcsuite/btcd/btcutil" @@ -233,17 +232,17 @@ func runCPFP(net *lntest.NetworkHarness, t *harnessTest, // testAnchorReservedValue tests that we won't allow sending transactions when // that would take the value we reserve for anchor fee bumping out of our // wallet. -func testAnchorReservedValue(net *lntest.NetworkHarness, t *harnessTest) { +func testAnchorReservedValue(ht *lntemp.HarnessTest) { // Start two nodes supporting anchor channels. args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS) - alice := net.NewNode(t.t, "Alice", args) - defer shutdownAndAssert(net, t, alice) - bob := net.NewNode(t.t, "Bob", args) - defer shutdownAndAssert(net, t, bob) + // NOTE: we cannot reuse the standby node here as the test requires the + // node to start with no UTXOs. + alice := ht.NewNode("Alice", args) + bob := ht.Bob + ht.RestartNodeWithExtraArgs(bob, args) - ctxb := context.Background() - net.ConnectNodes(t.t, alice, bob) + ht.ConnectNodes(alice, bob) // Send just enough coins for Alice to open a channel without a change // output. @@ -252,100 +251,73 @@ func testAnchorReservedValue(net *lntest.NetworkHarness, t *harnessTest) { feeEst = 8000 ) - net.SendCoins(t.t, chanAmt+feeEst, alice) + ht.FundCoins(chanAmt+feeEst, alice) // wallet, without a change output. This should not be allowed. - resErr := lnwallet.ErrReservedValueInvalidated.Error() - - _, err := net.OpenChannel( - alice, bob, lntest.OpenChannelParams{ + ht.OpenChannelAssertErr( + alice, bob, lntemp.OpenChannelParams{ Amt: chanAmt, - }, + }, lnwallet.ErrReservedValueInvalidated, ) - if err == nil || !strings.Contains(err.Error(), resErr) { - t.Fatalf("expected failure, got: %v", err) - } // Alice opens a smaller channel. This works since it will have a // change output. - aliceChanPoint1 := openChannelAndAssert( - t, net, alice, bob, lntest.OpenChannelParams{ - Amt: chanAmt / 4, - }, + chanPoint1 := ht.OpenChannel( + alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4}, ) // If Alice tries to open another anchor channel to Bob, Bob should not // reject it as he is not contributing any funds. - aliceChanPoint2 := openChannelAndAssert( - t, net, alice, bob, lntest.OpenChannelParams{ - Amt: chanAmt / 4, - }, + chanPoint2 := ht.OpenChannel( + alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4}, ) - // Similarly, if Alice tries to open a legacy channel to Bob, Bob should - // not reject it as he is not contributing any funds. We'll restart Bob - // to remove his support for anchors. - err = net.RestartNode(bob, nil) - require.NoError(t.t, err) - aliceChanPoint3 := openChannelAndAssert( - t, net, alice, bob, lntest.OpenChannelParams{ - Amt: chanAmt / 4, - }, + // Similarly, if Alice tries to open a legacy channel to Bob, Bob + // should not reject it as he is not contributing any funds. We'll + // restart Bob to remove his support for anchors. + ht.RestartNode(bob) + + // Before opening the channel, make sure the nodes are connected. + ht.EnsureConnected(alice, bob) + + chanPoint3 := ht.OpenChannel( + alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4}, ) - - chanPoints := []*lnrpc.ChannelPoint{ - aliceChanPoint1, aliceChanPoint2, aliceChanPoint3, - } - for _, chanPoint := range chanPoints { - err = alice.WaitForNetworkChannelOpen(chanPoint) - require.NoError(t.t, err) - - err = bob.WaitForNetworkChannelOpen(chanPoint) - require.NoError(t.t, err) - } + chanPoints := []*lnrpc.ChannelPoint{chanPoint1, chanPoint2, chanPoint3} // Alice tries to send all coins to an internal address. This is // allowed, since the final wallet balance will still be above the // reserved value. - addrReq := &lnrpc.NewAddressRequest{ + req := &lnrpc.NewAddressRequest{ Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH, } - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - resp, err := alice.NewAddress(ctxt, addrReq) - require.NoError(t.t, err) + resp := alice.RPC.NewAddress(req) sweepReq := &lnrpc.SendCoinsRequest{ Addr: resp.Address, SendAll: true, } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - _, err = alice.SendCoins(ctxt, sweepReq) - require.NoError(t.t, err) + alice.RPC.SendCoins(sweepReq) - block := mineBlocks(t, net, 1, 1)[0] + block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] + + assertNumTxInAndTxOut := func(tx *wire.MsgTx, in, out int) { + require.Len(ht, tx.TxIn, in, "num inputs not matched") + require.Len(ht, tx.TxOut, out, "num outputs not matched") + } // The sweep transaction should have exactly one input, the change from // the previous SendCoins call. sweepTx := block.Transactions[1] - if len(sweepTx.TxIn) != 1 { - t.Fatalf("expected 1 inputs instead have %v", len(sweepTx.TxIn)) - } // It should have a single output. - if len(sweepTx.TxOut) != 1 { - t.Fatalf("expected 1 output instead have %v", len(sweepTx.TxOut)) - } + assertNumTxInAndTxOut(sweepTx, 1, 1) // Wait for Alice to see her balance as confirmed. waitForConfirmedBalance := func() int64 { var balance int64 err := wait.NoError(func() error { - req := &lnrpc.WalletBalanceRequest{} - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err := alice.WalletBalance(ctxt, req) - if err != nil { - return err - } + resp := alice.RPC.WalletBalance() if resp.TotalBalance == 0 { return fmt.Errorf("no balance") @@ -358,93 +330,51 @@ func testAnchorReservedValue(net *lntest.NetworkHarness, t *harnessTest) { balance = resp.TotalBalance return nil }, defaultTimeout) - require.NoError(t.t, err) + require.NoError(ht, err, "timeout checking alice's balance") return balance } - _ = waitForConfirmedBalance() + waitForConfirmedBalance() // Alice tries to send all funds to an external address, the reserved // value must stay in her wallet. - minerAddr, err := net.Miner.NewAddress() - require.NoError(t.t, err) + minerAddr := ht.Miner.NewMinerAddress() sweepReq = &lnrpc.SendCoinsRequest{ Addr: minerAddr.String(), SendAll: true, } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - _, err = alice.SendCoins(ctxt, sweepReq) - require.NoError(t.t, err) + alice.RPC.SendCoins(sweepReq) // We'll mine a block which should include the sweep transaction we // generated above. - block = mineBlocks(t, net, 1, 1)[0] + block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] // The sweep transaction should have exactly one inputs as we only had // the single output from above in the wallet. sweepTx = block.Transactions[1] - if len(sweepTx.TxIn) != 1 { - t.Fatalf("expected 1 inputs instead have %v", len(sweepTx.TxIn)) - } // It should have two outputs, one being the miner address, the other // one being the reserve going back to our wallet. - if len(sweepTx.TxOut) != 2 { - t.Fatalf("expected 2 outputs instead have %v", len(sweepTx.TxOut)) - } + assertNumTxInAndTxOut(sweepTx, 1, 2) // The reserved value is now back in Alice's wallet. aliceBalance := waitForConfirmedBalance() - // The reserved value should be equal to the required reserve for anchor - // channels. - walletBalanceResp, err := alice.WalletBalance( - ctxb, &lnrpc.WalletBalanceRequest{}, - ) - require.NoError(t.t, err) - require.Equal( - t.t, aliceBalance, walletBalanceResp.ReservedBalanceAnchorChan, - ) - - additionalChannels := int64(1) - - // Required reserve when additional channels are provided. - requiredReserveResp, err := alice.WalletKitClient.RequiredReserve( - ctxb, &walletrpc.RequiredReserveRequest{ - AdditionalPublicChannels: uint32(additionalChannels), - }, - ) - require.NoError(t.t, err) - - additionalReservedValue := btcutil.Amount(additionalChannels * - int64(lnwallet.AnchorChanReservedValue)) - totalReserved := btcutil.Amount(aliceBalance) + additionalReservedValue - - // The total reserved value should not exceed the maximum value reserved - // for anchor channels. - if totalReserved > lnwallet.MaxAnchorChanReservedValue { - totalReserved = lnwallet.MaxAnchorChanReservedValue - } - require.Equal( - t.t, int64(totalReserved), requiredReserveResp.RequiredReserve, - ) - // Alice closes channel, should now be allowed to send everything to an // external address. for _, chanPoint := range chanPoints { - closeChannelAndAssert(t, net, alice, chanPoint, false) + ht.CloseChannel(alice, chanPoint) } newBalance := waitForConfirmedBalance() - if newBalance <= aliceBalance { - t.Fatalf("Alice's balance did not increase after channel close") - } + require.Greater(ht, newBalance, aliceBalance, + "Alice's balance did not increase after channel close") // Assert there are no open or pending channels anymore. - assertNumPendingChannels(t, alice, 0, 0) - assertNodeNumChannels(t, alice, 0) + ht.AssertNumWaitingClose(alice, 0) + ht.AssertNodeNumChannels(alice, 0) // We'll wait for the balance to reflect that the channel has been // closed and the funds are in the wallet. @@ -452,25 +382,18 @@ func testAnchorReservedValue(net *lntest.NetworkHarness, t *harnessTest) { Addr: minerAddr.String(), SendAll: true, } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - _, err = alice.SendCoins(ctxt, sweepReq) - require.NoError(t.t, err) + alice.RPC.SendCoins(sweepReq) // We'll mine a block which should include the sweep transaction we // generated above. - block = mineBlocks(t, net, 1, 1)[0] + block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] // The sweep transaction should have four inputs, the change output from // the previous sweep, and the outputs from the coop closed channels. sweepTx = block.Transactions[1] - if len(sweepTx.TxIn) != 4 { - t.Fatalf("expected 4 inputs instead have %v", len(sweepTx.TxIn)) - } // It should have a single output. - if len(sweepTx.TxOut) != 1 { - t.Fatalf("expected 1 output instead have %v", len(sweepTx.TxOut)) - } + assertNumTxInAndTxOut(sweepTx, 4, 1) } // genAnchorSweep generates a "3rd party" anchor sweeping from an existing one. diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index 1b4deda3a..c2dde1c9c 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -106,10 +106,6 @@ var allTestCases = []*testCase{ name: "cpfp", test: testCPFP, }, - { - name: "anchors reserved value", - test: testAnchorReservedValue, - }, { name: "macaroon authentication", test: testMacaroonAuthentication,