diff --git a/itest/lnd_revocation_test.go b/itest/lnd_revocation_test.go index 5074a3f02..c2508b885 100644 --- a/itest/lnd_revocation_test.go +++ b/itest/lnd_revocation_test.go @@ -109,7 +109,11 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // broadcasting his current channel state. This is actually the // commitment transaction of a prior *revoked* state, so he'll soon // feel the wrath of Carol's retribution. - _, breachTXID := ht.CloseChannelAssertPending(bob, chanPoint, true) + _, breachCloseUpd := ht.CloseChannelAssertPending(bob, chanPoint, true) + closeUpd := breachCloseUpd.GetClosePending() + require.NotNil(ht, closeUpd) + breachTXID, err := chainhash.NewHash(closeUpd.Txid) + require.NoError(ht, err) // Here, Carol sees Bob's breach transaction in the mempool, but is // waiting for it to confirm before continuing her retribution. We @@ -122,13 +126,13 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // update, then ensure that the closing transaction was included in the // block. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.AssertTxInBlock(block, breachTXID) + ht.AssertTxInBlock(block, *breachTXID) // Construct to_remote output which pays to Bob. Based on the output // ordering, the first output in this breach tx is the to_remote // output. toRemoteOp := wire.OutPoint{ - Hash: breachTXID, + Hash: *breachTXID, Index: 0, } @@ -151,7 +155,7 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // Assert that all the inputs of this transaction are spending outputs // generated by Bob's breach transaction above. for _, txIn := range justiceTx.TxIn { - require.Equal(ht, breachTXID, txIn.PreviousOutPoint.Hash, + require.Equal(ht, *breachTXID, txIn.PreviousOutPoint.Hash, "justice tx not spending commitment utxo") } @@ -296,7 +300,7 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest, // broadcasting her current channel state. This is actually the // commitment transaction of a prior *revoked* state, so she'll soon // feel the wrath of Dave's retribution. - stream, closeTxID := ht.CloseChannelAssertPending( + stream, closeUpdate := ht.CloseChannelAssertPending( carol, chanPoint, true, ) @@ -310,9 +314,11 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest, // state and continues exacting justice after his node restarts. ht.RestartNode(dave) + closeTxID := closeUpdate.GetClosePending().Txid + // The breachTXID should match the above closeTxID. breachTXID := ht.WaitForChannelCloseEvent(stream) - require.EqualValues(ht, breachTXID, closeTxID) + require.EqualValues(ht, breachTXID[:], closeTxID) // Construct to_local output which pays to Dave. Based on the output // ordering, the first output in this breach tx is the to_local @@ -543,9 +549,13 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest, // broadcasting her current channel state. This is actually the // commitment transaction of a prior *revoked* state, so she'll soon // feel the wrath of Dave's retribution. - closeUpdates, closeTxID := ht.CloseChannelAssertPending( + closeUpdates, closeUpd := ht.CloseChannelAssertPending( carol, chanPoint, true, ) + pendingCloseUpd := closeUpd.GetClosePending() + require.NotNil(ht, pendingCloseUpd) + closeTxID, err := chainhash.NewHash(pendingCloseUpd.Txid) + require.NoError(ht, err) // Generate a single block to mine the breach transaction. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] @@ -593,7 +603,7 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest, return nil, errNotFound } - err := wait.NoError(func() error { + err = wait.NoError(func() error { txid, err := findJusticeTx() if err != nil { return err diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index db3e2171e..afc237713 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/fn/v2" @@ -1963,8 +1964,8 @@ func testBumpForceCloseFee(ht *lntest.HarnessTest) { ht.FundCoinsP2TR(btcutil.SatoshiPerBitcoin, alice) // Alice force closes the channel which has no HTLCs at stake. - _, closingTxID := ht.CloseChannelAssertPending(alice, chanPoint, true) - require.NotNil(ht, closingTxID) + _, closeUpdates := ht.CloseChannelAssertPending(alice, chanPoint, true) + require.NotNil(ht, closeUpdates) // Alice should see one waiting close channel. ht.AssertNumWaitingClose(alice, 1) @@ -1974,8 +1975,10 @@ func testBumpForceCloseFee(ht *lntest.HarnessTest) { ht.AssertNumPendingSweeps(alice, 2) // Calculate the commitment tx fee rate. - closingTx := ht.AssertTxInMempool(closingTxID) - require.NotNil(ht, closingTx) + pendingClose := closeUpdates.GetClosePending() + closeTxid, err := chainhash.NewHash(pendingClose.Txid) + require.NoError(ht, err) + closingTx := ht.AssertTxInMempool(*closeTxid) // The default commitment fee for anchor channels is capped at 2500 // sat/kw but there might be some inaccuracies because of the witness diff --git a/itest/lnd_watchtower_test.go b/itest/lnd_watchtower_test.go index 28bb65a63..1b63f9063 100644 --- a/itest/lnd_watchtower_test.go +++ b/itest/lnd_watchtower_test.go @@ -491,7 +491,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // broadcasting his current channel state. This is actually the // commitment transaction of a prior *revoked* state, so he'll soon // feel the wrath of Dave's retribution. - closeUpdates, closeTxID := ht.CloseChannelAssertPending( + closeUpdates, pendingClose := ht.CloseChannelAssertPending( carol, chanPoint, true, ) @@ -504,7 +504,8 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, ht.AssertTxInBlock(block, breachTXID) // The breachTXID should match the above closeTxID. - require.EqualValues(ht, breachTXID, closeTxID) + closeTxID := pendingClose.GetClosePending().Txid + require.EqualValues(ht, breachTXID[:], closeTxID) // Query the mempool for Dave's justice transaction, this should be // broadcast as Carol's contract breaching transaction gets confirmed diff --git a/lntest/harness.go b/lntest/harness.go index 6df1d9ffa..f7a8eec65 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -1208,14 +1208,40 @@ func (h *HarnessTest) OpenChannelAssertErr(srcNode, destNode *node.HarnessNode, "error returned, want %v, got %v", expectedErr, err) } +// closeChannelOpts holds the options for closing a channel. +type closeChannelOpts struct { + feeRate fn.Option[chainfee.SatPerVByte] +} + +// CloseChanOpt is a functional option to modify the way we close a channel. +type CloseChanOpt func(*closeChannelOpts) + +// WithCoopCloseFeeRate is a functional option to set the fee rate for a coop +// close attempt. +func WithCoopCloseFeeRate(rate chainfee.SatPerVByte) CloseChanOpt { + return func(o *closeChannelOpts) { + o.feeRate = fn.Some(rate) + } +} + +// defaultCloseOpts returns the set of default close options. +func defaultCloseOpts() *closeChannelOpts { + return &closeChannelOpts{} +} + // CloseChannelAssertPending attempts to close the channel indicated by the // passed channel point, initiated by the passed node. Once the CloseChannel // rpc is called, it will consume one event and assert it's a close pending // event. In addition, it will check that the closing tx can be found in the // mempool. func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode, - cp *lnrpc.ChannelPoint, - force bool) (rpc.CloseChanClient, chainhash.Hash) { + cp *lnrpc.ChannelPoint, force bool, + opts ...CloseChanOpt) (rpc.CloseChanClient, *lnrpc.CloseStatusUpdate) { + + closeOpts := defaultCloseOpts() + for _, optFunc := range opts { + optFunc(closeOpts) + } // Calls the rpc to close the channel. closeReq := &lnrpc.CloseChannelRequest{ @@ -1224,10 +1250,9 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode, NoWait: true, } - // For coop close, we use a default confg target of 6. - if !force { - closeReq.TargetConf = 6 - } + closeOpts.feeRate.WhenSome(func(feeRate chainfee.SatPerVByte) { + closeReq.SatPerVbyte = uint64(feeRate) + }) var ( stream rpc.CloseChanClient @@ -1260,7 +1285,7 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode, // Assert the closing tx is in the mempool. h.miner.AssertTxInMempool(*closeTxid) - return stream, *closeTxid + return stream, event } // CloseChannel attempts to coop close a non-anchored channel identified by the