@@ -16,6 +16,7 @@ import (
16
16
"github.com/lightninglabs/loop/loopdb"
17
17
"github.com/lightninglabs/loop/swap"
18
18
"github.com/lightninglabs/loop/utils"
19
+ "github.com/lightningnetwork/lnd/clock"
19
20
"github.com/lightningnetwork/lnd/input"
20
21
"github.com/lightningnetwork/lnd/lntypes"
21
22
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
@@ -44,7 +45,7 @@ const (
44
45
45
46
// defaultTestnetPublishDelay is the default publish delay that is used
46
47
// for testnet.
47
- defaultPublishDelay = 500 * time .Millisecond
48
+ defaultTestnetPublishDelay = 500 * time .Millisecond
48
49
)
49
50
50
51
type BatcherStore interface {
@@ -253,6 +254,23 @@ type Batcher struct {
253
254
// exit.
254
255
wg sync.WaitGroup
255
256
257
+ // clock provides methods to work with time and timers.
258
+ clock clock.Clock
259
+
260
+ // initialDelay is the delay of first batch publishing after creation.
261
+ // It only affects newly created batches, not batches loaded from DB,
262
+ // so publishing does happen in case of a daemon restart (especially
263
+ // important in case of a crashloop). If a sweep is about to expire
264
+ // (time until timeout is less that 2x initialDelay), then waiting is
265
+ // skipped.
266
+ initialDelay time.Duration
267
+
268
+ // publishDelay is the delay of batch publishing that is applied in the
269
+ // beginning, after the appearance of a new block in the network or
270
+ // after the end of initial delay. For batches recovered from DB this
271
+ // value is always 0s, regardless of this setting.
272
+ publishDelay time.Duration
273
+
256
274
// customFeeRate provides custom min fee rate per swap. The batch uses
257
275
// max of the fee rates of its swaps. In this mode confTarget is
258
276
// ignored and fee bumping by sweepbatcher is disabled.
@@ -267,6 +285,23 @@ type Batcher struct {
267
285
268
286
// BatcherConfig holds batcher configuration.
269
287
type BatcherConfig struct {
288
+ // clock provides methods to work with time and timers.
289
+ clock clock.Clock
290
+
291
+ // initialDelay is the delay of first batch publishing after creation.
292
+ // It only affects newly created batches, not batches loaded from DB,
293
+ // so publishing does happen in case of a daemon restart (especially
294
+ // important in case of a crashloop). If a sweep is about to expire
295
+ // (time until timeout is less that 2x initialDelay), then waiting is
296
+ // skipped.
297
+ initialDelay time.Duration
298
+
299
+ // publishDelay is the delay of batch publishing that is applied in the
300
+ // beginning, after the appearance of a new block in the network or
301
+ // after the end of initial delay. For batches recovered from DB this
302
+ // value is always 0s, regardless of this setting.
303
+ publishDelay time.Duration
304
+
270
305
// customFeeRate provides custom min fee rate per swap. The batch uses
271
306
// max of the fee rates of its swaps. In this mode confTarget is
272
307
// ignored and fee bumping by sweepbatcher is disabled.
@@ -282,6 +317,37 @@ type BatcherConfig struct {
282
317
// BatcherOption configures batcher behaviour.
283
318
type BatcherOption func (* BatcherConfig )
284
319
320
+ // WithClock sets the clock used by sweepbatcher and its batches. It is needed
321
+ // to manipulate time in tests.
322
+ func WithClock (clock clock.Clock ) BatcherOption {
323
+ return func (cfg * BatcherConfig ) {
324
+ cfg .clock = clock
325
+ }
326
+ }
327
+
328
+ // WithInitialDelay instructs sweepbatcher to wait for the duration provided
329
+ // after new batch creation before it is first published. This facilitates
330
+ // better grouping. Defaults to 0s (no initial delay). If a sweep is about
331
+ // to expire (time until timeout is less that 2x initialDelay), then waiting
332
+ // is skipped.
333
+ func WithInitialDelay (initialDelay time.Duration ) BatcherOption {
334
+ return func (cfg * BatcherConfig ) {
335
+ cfg .initialDelay = initialDelay
336
+ }
337
+ }
338
+
339
+ // WithPublishDelay sets the delay of batch publishing that is applied in the
340
+ // beginning, after the appearance of a new block in the network or after the
341
+ // end of initial delay (see WithInitialDelay). It is needed to prevent
342
+ // unnecessary transaction publishments when a spend is detected on that block.
343
+ // Default value depends on the network: 5 seconds in mainnet, 0.5s in testnet.
344
+ // For batches recovered from DB this value is always 0s.
345
+ func WithPublishDelay (publishDelay time.Duration ) BatcherOption {
346
+ return func (cfg * BatcherConfig ) {
347
+ cfg .publishDelay = publishDelay
348
+ }
349
+ }
350
+
285
351
// WithCustomFeeRate instructs sweepbatcher not to fee bump itself and rely on
286
352
// external source of fee rates (FeeRateProvider). To apply a fee rate change,
287
353
// the caller should re-add the sweep by calling AddSweep.
@@ -315,6 +381,11 @@ func NewBatcher(wallet lndclient.WalletKitClient,
315
381
opt (& cfg )
316
382
}
317
383
384
+ // If WithClock was not provided, use default clock.
385
+ if cfg .clock == nil {
386
+ cfg .clock = clock .NewDefaultClock ()
387
+ }
388
+
318
389
if cfg .customMuSig2Signer != nil && musig2ServerSigner != nil {
319
390
panic ("customMuSig2Signer must not be used with " +
320
391
"musig2ServerSigner" )
@@ -334,6 +405,9 @@ func NewBatcher(wallet lndclient.WalletKitClient,
334
405
chainParams : chainparams ,
335
406
store : store ,
336
407
sweepStore : sweepStore ,
408
+ clock : cfg .clock ,
409
+ initialDelay : cfg .initialDelay ,
410
+ publishDelay : cfg .publishDelay ,
337
411
customFeeRate : cfg .customFeeRate ,
338
412
customMuSig2Signer : cfg .customMuSig2Signer ,
339
413
}
@@ -536,8 +610,22 @@ func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) {
536
610
cfg .batchPublishDelay = defaultMainnetPublishDelay
537
611
538
612
default :
539
- cfg .batchPublishDelay = defaultPublishDelay
613
+ cfg .batchPublishDelay = defaultTestnetPublishDelay
614
+ }
615
+
616
+ if b .publishDelay != 0 {
617
+ if b .publishDelay < 0 {
618
+ return nil , fmt .Errorf ("negative publishDelay: %v" ,
619
+ b .publishDelay )
620
+ }
621
+ cfg .batchPublishDelay = b .publishDelay
622
+ }
623
+
624
+ if b .initialDelay < 0 {
625
+ return nil , fmt .Errorf ("negative initialDelay: %v" ,
626
+ b .initialDelay )
540
627
}
628
+ cfg .initialDelay = b .initialDelay
541
629
542
630
batchKit := b .newBatchKit ()
543
631
@@ -626,6 +714,9 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
626
714
627
715
cfg := b .newBatchConfig (batch .cfg .maxTimeoutDistance )
628
716
717
+ // Note that initialDelay and batchPublishDelay are 0 for batches
718
+ // recovered from DB so publishing happen in case of a daemon restart
719
+ // (especially important in case of a crashloop).
629
720
newBatch , err := NewBatchFromDB (cfg , batchKit )
630
721
if err != nil {
631
722
return fmt .Errorf ("failed in NewBatchFromDB: %w" , err )
@@ -934,6 +1025,7 @@ func (b *Batcher) newBatchConfig(maxTimeoutDistance int32) batchConfig {
934
1025
maxTimeoutDistance : maxTimeoutDistance ,
935
1026
noBumping : b .customFeeRate != nil ,
936
1027
customMuSig2Signer : b .customMuSig2Signer ,
1028
+ clock : b .clock ,
937
1029
}
938
1030
}
939
1031
0 commit comments