Skip to content

Commit c4ec1cb

Browse files
committed
sweepbatcher: load from DB preserves confTarget
It used to be set to default (defaultBatchConfTarget = 12) which could in theory affect fee rate if updateRbfRate() and publish() were not called before the batch was saved. (Unlikely scenario.)
1 parent 5516731 commit c4ec1cb

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

sweepbatcher/sweep_batch.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,20 @@ func NewBatch(cfg batchConfig, bk batchKit) *batch {
316316
}
317317

318318
// NewBatchFromDB creates a new batch that already existed in storage.
319-
func NewBatchFromDB(cfg batchConfig, bk batchKit) *batch {
319+
func NewBatchFromDB(cfg batchConfig, bk batchKit) (*batch, error) {
320+
// Make sure the batch is not empty. We have checked this in
321+
// spinUpBatchFromDB before calling NewBatchFromDB.
322+
if len(bk.sweeps) == 0 {
323+
return nil, fmt.Errorf("empty batch is not allowed")
324+
}
325+
326+
// Assign batchConfTarget to primary sweep's confTarget.
327+
for _, sweep := range bk.sweeps {
328+
if sweep.swapHash == bk.primaryID {
329+
cfg.batchConfTarget = sweep.confTarget
330+
}
331+
}
332+
320333
return &batch{
321334
id: bk.id,
322335
state: bk.state,
@@ -343,7 +356,7 @@ func NewBatchFromDB(cfg batchConfig, bk batchKit) *batch {
343356
store: bk.store,
344357
log: bk.log,
345358
cfg: &cfg,
346-
}
359+
}, nil
347360
}
348361

349362
// addSweep tries to add a sweep to the batch. If this is the first sweep being

sweepbatcher/sweep_batcher.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,10 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
488488
batchConfTarget: defaultBatchConfTarget,
489489
}
490490

491-
newBatch := NewBatchFromDB(cfg, batchKit)
491+
newBatch, err := NewBatchFromDB(cfg, batchKit)
492+
if err != nil {
493+
return fmt.Errorf("failed in NewBatchFromDB: %w", err)
494+
}
492495

493496
// We add the batch to our map of batches and start it.
494497
b.batches[batch.id] = newBatch

sweepbatcher/sweep_batcher_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,3 +1115,119 @@ func TestRestoringEmptyBatch(t *testing.T) {
11151115

11161116
checkBatcherError(t, runErr)
11171117
}
1118+
1119+
// TestRestoringPreservesConfTarget tests that after the batch is written to DB
1120+
// and loaded back, its batchConfTarget value is preserved.
1121+
func TestRestoringPreservesConfTarget(t *testing.T) {
1122+
defer test.Guard(t)()
1123+
1124+
lnd := test.NewMockLnd()
1125+
ctx, cancel := context.WithCancel(context.Background())
1126+
1127+
store := loopdb.NewStoreMock(t)
1128+
1129+
batcherStore := NewStoreMock(store)
1130+
1131+
batcher := NewBatcher(lnd.WalletKit, lnd.ChainNotifier, lnd.Signer,
1132+
testMuSig2SignSweep, nil, lnd.ChainParams, batcherStore, store)
1133+
1134+
var wg sync.WaitGroup
1135+
wg.Add(1)
1136+
1137+
var runErr error
1138+
go func() {
1139+
defer wg.Done()
1140+
runErr = batcher.Run(ctx)
1141+
}()
1142+
1143+
// Wait for the batcher to be initialized.
1144+
<-batcher.initDone
1145+
1146+
// Create a sweep request.
1147+
sweepReq := SweepRequest{
1148+
SwapHash: lntypes.Hash{1, 1, 1},
1149+
Value: 111,
1150+
Outpoint: wire.OutPoint{
1151+
Hash: chainhash.Hash{1, 1},
1152+
Index: 1,
1153+
},
1154+
Notifier: &dummyNotifier,
1155+
}
1156+
1157+
swap := &loopdb.LoopOutContract{
1158+
SwapContract: loopdb.SwapContract{
1159+
CltvExpiry: 111,
1160+
AmountRequested: 111,
1161+
},
1162+
1163+
SwapInvoice: swapInvoice,
1164+
SweepConfTarget: 123,
1165+
}
1166+
1167+
err := store.CreateLoopOut(ctx, sweepReq.SwapHash, swap)
1168+
require.NoError(t, err)
1169+
store.AssertLoopOutStored()
1170+
1171+
// Deliver sweep request to batcher.
1172+
require.NoError(t, batcher.AddSweep(&sweepReq))
1173+
1174+
// Since a batch was created we check that it registered for its primary
1175+
// sweep's spend.
1176+
<-lnd.RegisterSpendChannel
1177+
1178+
// Once batcher receives sweep request it will eventually spin up a
1179+
// batch.
1180+
require.Eventually(t, func() bool {
1181+
// Make sure that the sweep was stored and we have exactly one
1182+
// active batch, with one sweep and proper batchConfTarget.
1183+
return batcherStore.AssertSweepStored(sweepReq.SwapHash) &&
1184+
len(batcher.batches) == 1 &&
1185+
len(batcher.batches[0].sweeps) == 1 &&
1186+
batcher.batches[0].cfg.batchConfTarget == 123
1187+
}, test.Timeout, eventuallyCheckFrequency)
1188+
1189+
// Make sure we have stored the batch.
1190+
batches, err := batcherStore.FetchUnconfirmedSweepBatches(ctx)
1191+
require.NoError(t, err)
1192+
require.Len(t, batches, 1)
1193+
1194+
// Now make it quit by canceling the context.
1195+
cancel()
1196+
wg.Wait()
1197+
1198+
// Make sure the batcher existed without an error.
1199+
checkBatcherError(t, runErr)
1200+
1201+
// Now launch it again.
1202+
batcher = NewBatcher(lnd.WalletKit, lnd.ChainNotifier, lnd.Signer,
1203+
testMuSig2SignSweep, nil, lnd.ChainParams, batcherStore, store)
1204+
ctx, cancel = context.WithCancel(context.Background())
1205+
wg.Add(1)
1206+
go func() {
1207+
defer wg.Done()
1208+
runErr = batcher.Run(ctx)
1209+
}()
1210+
1211+
// Wait for the batcher to be initialized.
1212+
<-batcher.initDone
1213+
1214+
// Wait for batch to load.
1215+
require.Eventually(t, func() bool {
1216+
return batcherStore.AssertSweepStored(sweepReq.SwapHash) &&
1217+
len(batcher.batches) == 1 &&
1218+
len(batcher.batches[0].sweeps) == 1
1219+
}, test.Timeout, eventuallyCheckFrequency)
1220+
1221+
// Make sure batchConfTarget was preserved.
1222+
require.Equal(t, 123, int(batcher.batches[0].cfg.batchConfTarget))
1223+
1224+
// Expect registration for spend notification.
1225+
<-lnd.RegisterSpendChannel
1226+
1227+
// Now make it quit by canceling the context.
1228+
cancel()
1229+
wg.Wait()
1230+
1231+
// Make sure the batcher existed without an error.
1232+
checkBatcherError(t, runErr)
1233+
}

0 commit comments

Comments
 (0)