@@ -12,6 +12,7 @@ import (
12
12
"github.com/lightningnetwork/lnd/lntest"
13
13
"github.com/lightningnetwork/lnd/lntest/wait"
14
14
"github.com/lightningnetwork/lnd/lntypes"
15
+ "github.com/lightningnetwork/lnd/lnwallet/chainfee"
15
16
"github.com/stretchr/testify/require"
16
17
)
17
18
@@ -93,14 +94,17 @@ func coopCloseWithHTLCs(ht *lntest.HarnessTest) {
93
94
// closure is set up. Let's settle the invoice.
94
95
alice .RPC .SettleInvoice (preimage [:])
95
96
96
- // Pull the instant update off the wire to clear the path for the
97
- // close pending update .
98
- _ , err := closeClient .Recv ()
97
+ // Pull the instant update off the wire and make sure the number of
98
+ // pending HTLCs is as expected .
99
+ update , err := closeClient .Recv ()
99
100
require .NoError (ht , err )
101
+ closeInstant := update .GetCloseInstant ()
102
+ require .NotNil (ht , closeInstant )
103
+ require .Equal (ht , closeInstant .NumPendingHtlcs , int32 (1 ))
100
104
101
105
// Wait for the next channel closure update. Now that we have settled
102
106
// the only HTLC this should be imminent.
103
- update , err : = closeClient .Recv ()
107
+ update , err = closeClient .Recv ()
104
108
require .NoError (ht , err )
105
109
106
110
// This next update should be a GetClosePending as it should be the
@@ -243,3 +247,76 @@ func coopCloseWithHTLCsWithRestart(ht *lntest.HarnessTest) {
243
247
// Show that the address used is the one she requested.
244
248
require .Equal (ht , outputDetail .Address , newAddr .Address )
245
249
}
250
+
251
+ // testCoopCloseExceedsMaxFee tests that we fail the coop close process if
252
+ // the max fee rate exceeds the expected fee rate for the initial closing fee
253
+ // proposal.
254
+ func testCoopCloseExceedsMaxFee (ht * lntest.HarnessTest ) {
255
+ const chanAmt = 1000000
256
+
257
+ // Create a channel Alice->Bob.
258
+ chanPoints , nodes := ht .CreateSimpleNetwork (
259
+ [][]string {nil , nil }, lntest.OpenChannelParams {
260
+ Amt : chanAmt ,
261
+ },
262
+ )
263
+
264
+ alice , _ := nodes [0 ], nodes [1 ]
265
+ chanPoint := chanPoints [0 ]
266
+
267
+ // Set the fee estimate for one block to 10 sat/vbyte.
268
+ ht .SetFeeEstimateWithConf (chainfee .SatPerVByte (10 ).FeePerKWeight (), 1 )
269
+
270
+ // Have alice attempt to close the channel. We expect the initial fee
271
+ // rate to exceed the max fee rate for the closing transaction so we
272
+ // fail the closing process.
273
+ req := & lnrpc.CloseChannelRequest {
274
+ ChannelPoint : chanPoint ,
275
+ MaxFeePerVbyte : 5 ,
276
+ NoWait : true ,
277
+ TargetConf : 1 ,
278
+ }
279
+ err := ht .CloseChannelAssertErr (alice , req )
280
+ require .Contains (ht , err .Error (), "max_fee_per_vbyte (1250 sat/kw) is " +
281
+ "less than the required fee rate (2500 sat/kw)" )
282
+
283
+ // Now close the channel with a appropriate max fee rate.
284
+ closeClient := alice .RPC .CloseChannel (& lnrpc.CloseChannelRequest {
285
+ ChannelPoint : chanPoint ,
286
+ NoWait : true ,
287
+ TargetConf : 1 ,
288
+ MaxFeePerVbyte : 10 ,
289
+ })
290
+
291
+ // Pull the instant update off the wire to clear the path for the
292
+ // close pending update. Moreover confirm that there are no pending
293
+ // HTLCs on the channel.
294
+ update , err := closeClient .Recv ()
295
+ require .NoError (ht , err )
296
+ closeInstant := update .GetCloseInstant ()
297
+ require .NotNil (ht , closeInstant )
298
+ require .Equal (ht , closeInstant .NumPendingHtlcs , int32 (0 ))
299
+
300
+ // Wait for the channel to be closed.
301
+ update , err = closeClient .Recv ()
302
+ require .NoError (ht , err )
303
+
304
+ // This next update should be a GetClosePending as it should be the
305
+ // negotiation of the coop close tx.
306
+ closePending := update .GetClosePending ()
307
+ require .NotNil (ht , closePending )
308
+
309
+ // Convert the txid we get from the PendingUpdate to a Hash so we can
310
+ // wait for it to be mined.
311
+ var closeTxid chainhash.Hash
312
+ require .NoError (
313
+ ht , closeTxid .SetBytes (closePending .Txid ),
314
+ "invalid closing txid" ,
315
+ )
316
+
317
+ // Wait for the close tx to be in the Mempool.
318
+ ht .AssertTxInMempool (closeTxid )
319
+
320
+ // Wait for it to get mined and finish tearing down.
321
+ ht .AssertStreamChannelCoopClosed (alice , chanPoint , false , closeClient )
322
+ }
0 commit comments