@@ -8,13 +8,15 @@ import (
8
8
"testing"
9
9
"time"
10
10
11
+ "github.com/btcsuite/btcd/btcec/v2"
11
12
"github.com/btcsuite/btcd/btcutil"
12
13
"github.com/btcsuite/btcd/chaincfg/chainhash"
13
14
"github.com/btcsuite/btcd/wire"
14
15
"github.com/lightninglabs/loop/loopdb"
15
16
"github.com/lightninglabs/loop/test"
16
17
"github.com/lightninglabs/loop/utils"
17
18
"github.com/lightningnetwork/lnd/chainntnfs"
19
+ "github.com/lightningnetwork/lnd/keychain"
18
20
"github.com/lightningnetwork/lnd/lntypes"
19
21
"github.com/stretchr/testify/require"
20
22
)
@@ -42,6 +44,20 @@ var destAddr = func() btcutil.Address {
42
44
return addr
43
45
}()
44
46
47
+ var senderKey , receiverKey [33 ]byte
48
+
49
+ func init () {
50
+ // Generate keys.
51
+ _ , senderPubKey := test .CreateKey (1 )
52
+ copy (senderKey [:], senderPubKey .SerializeCompressed ())
53
+ _ , receiverPubKey := test .CreateKey (2 )
54
+ copy (receiverKey [:], receiverPubKey .SerializeCompressed ())
55
+ }
56
+
57
+ func testVerifySchnorrSig (pubKey * btcec.PublicKey , hash , sig []byte ) error {
58
+ return nil
59
+ }
60
+
45
61
func testMuSig2SignSweep (ctx context.Context ,
46
62
protocolVersion loopdb.ProtocolVersion , swapHash lntypes.Hash ,
47
63
paymentAddr [32 ]byte , nonce []byte , sweepTxPsbt []byte ,
@@ -245,6 +261,103 @@ func testSweepBatcherBatchCreation(t *testing.T, store testStore,
245
261
require .True (t , batcherStore .AssertSweepStored (sweepReq3 .SwapHash ))
246
262
}
247
263
264
+ // testFeeBumping tests that sweep is RBFed with slightly higher fee rate after
265
+ // each block unless WithNoBumping is passed.
266
+ func testFeeBumping (t * testing.T , store testStore ,
267
+ batcherStore testBatcherStore , noFeeBumping bool ) {
268
+
269
+ defer test .Guard (t )()
270
+
271
+ lnd := test .NewMockLnd ()
272
+ ctx , cancel := context .WithCancel (context .Background ())
273
+ defer cancel ()
274
+
275
+ sweepStore , err := NewSweepFetcherFromSwapStore (store , lnd .ChainParams )
276
+ require .NoError (t , err )
277
+
278
+ // Disable fee bumping, if requested.
279
+ var opts []BatcherOption
280
+ if noFeeBumping {
281
+ opts = append (opts , WithNoBumping ())
282
+ }
283
+
284
+ batcher := NewBatcher (lnd .WalletKit , lnd .ChainNotifier , lnd .Signer ,
285
+ testMuSig2SignSweep , testVerifySchnorrSig , lnd .ChainParams ,
286
+ batcherStore , sweepStore , opts ... )
287
+ go func () {
288
+ err := batcher .Run (ctx )
289
+ checkBatcherError (t , err )
290
+ }()
291
+
292
+ // Create a sweep request.
293
+ sweepReq1 := SweepRequest {
294
+ SwapHash : lntypes.Hash {1 , 1 , 1 },
295
+ Value : 1_000_000 ,
296
+ Outpoint : wire.OutPoint {
297
+ Hash : chainhash.Hash {1 , 1 },
298
+ Index : 1 ,
299
+ },
300
+ Notifier : & SpendNotifier {
301
+ SpendChan : make (chan * SpendDetail , ntfnBufferSize ),
302
+ SpendErrChan : make (chan error , ntfnBufferSize ),
303
+ QuitChan : make (chan bool , ntfnBufferSize ),
304
+ },
305
+ }
306
+
307
+ swap1 := & loopdb.LoopOutContract {
308
+ SwapContract : loopdb.SwapContract {
309
+ CltvExpiry : 111 ,
310
+ AmountRequested : 1_000_000 ,
311
+ ProtocolVersion : loopdb .ProtocolVersionMuSig2 ,
312
+ HtlcKeys : loopdb.HtlcKeys {
313
+ SenderScriptKey : senderKey ,
314
+ ReceiverScriptKey : receiverKey ,
315
+ SenderInternalPubKey : senderKey ,
316
+ ReceiverInternalPubKey : receiverKey ,
317
+ ClientScriptKeyLocator : keychain.KeyLocator {
318
+ Family : 1 ,
319
+ Index : 2 ,
320
+ },
321
+ },
322
+ },
323
+
324
+ DestAddr : destAddr ,
325
+ SwapInvoice : swapInvoice ,
326
+ SweepConfTarget : 111 ,
327
+ }
328
+
329
+ err = store .CreateLoopOut (ctx , sweepReq1 .SwapHash , swap1 )
330
+ require .NoError (t , err )
331
+ store .AssertLoopOutStored ()
332
+
333
+ // Deliver sweep request to batcher.
334
+ require .NoError (t , batcher .AddSweep (& sweepReq1 ))
335
+
336
+ // Since a batch was created we check that it registered for its primary
337
+ // sweep's spend.
338
+ <- lnd .RegisterSpendChannel
339
+
340
+ // Wait for tx to be published.
341
+ tx1 := <- lnd .TxPublishChannel
342
+ out1 := tx1 .TxOut [0 ].Value
343
+
344
+ // Tick tock next block.
345
+ err = lnd .NotifyHeight (601 )
346
+ require .NoError (t , err )
347
+
348
+ // Wait for another sweep tx to be published.
349
+ tx2 := <- lnd .TxPublishChannel
350
+ out2 := tx2 .TxOut [0 ].Value
351
+
352
+ if noFeeBumping {
353
+ // Expect output to stay the same.
354
+ require .Equal (t , out1 , out2 , "expected out to stay the same" )
355
+ } else {
356
+ // Expect output to drop.
357
+ require .Greater (t , out1 , out2 , "expected out to drop" )
358
+ }
359
+ }
360
+
248
361
// testSweepBatcherSimpleLifecycle tests the simple lifecycle of the batches
249
362
// that are created and run by the batcher.
250
363
func testSweepBatcherSimpleLifecycle (t * testing.T , store testStore ,
@@ -1837,6 +1950,26 @@ func TestSweepBatcherBatchCreation(t *testing.T) {
1837
1950
runTests (t , testSweepBatcherBatchCreation )
1838
1951
}
1839
1952
1953
+ // TestFeeBumping tests that sweep is RBFed with slightly higher fee rate after
1954
+ // each block unless WithNoBumping is passed.
1955
+ func TestFeeBumping (t * testing.T ) {
1956
+ t .Run ("regular" , func (t * testing.T ) {
1957
+ runTests (t , func (t * testing.T , store testStore ,
1958
+ batcherStore testBatcherStore ) {
1959
+
1960
+ testFeeBumping (t , store , batcherStore , false )
1961
+ })
1962
+ })
1963
+
1964
+ t .Run ("WithNoBumping" , func (t * testing.T ) {
1965
+ runTests (t , func (t * testing.T , store testStore ,
1966
+ batcherStore testBatcherStore ) {
1967
+
1968
+ testFeeBumping (t , store , batcherStore , true )
1969
+ })
1970
+ })
1971
+ }
1972
+
1840
1973
// TestSweepBatcherSimpleLifecycle tests the simple lifecycle of the batches
1841
1974
// that are created and run by the batcher.
1842
1975
func TestSweepBatcherSimpleLifecycle (t * testing.T ) {
0 commit comments