-
Notifications
You must be signed in to change notification settings - Fork 119
sweepbatcher: do not fail on restoring empty batches #754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
939c9b4
c01e801
e5ade6a
14de8f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package sweepbatcher | |
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
@@ -46,36 +47,35 @@ const ( | |
type BatcherStore interface { | ||
// FetchUnconfirmedSweepBatches fetches all the batches from the | ||
// database that are not in a confirmed state. | ||
FetchUnconfirmedSweepBatches(ctx context.Context) ([]*dbBatch, | ||
error) | ||
FetchUnconfirmedSweepBatches(ctx context.Context) ([]*dbBatch, error) | ||
|
||
// InsertSweepBatch inserts a batch into the database, returning the id | ||
// of the inserted batch. | ||
InsertSweepBatch(ctx context.Context, | ||
batch *dbBatch) (int32, error) | ||
InsertSweepBatch(ctx context.Context, batch *dbBatch) (int32, error) | ||
|
||
// DropBatch drops a batch from the database. This should only be used | ||
// when a batch is empty. | ||
DropBatch(ctx context.Context, id int32) error | ||
|
||
// UpdateSweepBatch updates a batch in the database. | ||
UpdateSweepBatch(ctx context.Context, | ||
batch *dbBatch) error | ||
UpdateSweepBatch(ctx context.Context, batch *dbBatch) error | ||
|
||
// ConfirmBatch confirms a batch by setting its state to confirmed. | ||
ConfirmBatch(ctx context.Context, id int32) error | ||
|
||
// FetchBatchSweeps fetches all the sweeps that belong to a batch. | ||
FetchBatchSweeps(ctx context.Context, | ||
id int32) ([]*dbSweep, error) | ||
FetchBatchSweeps(ctx context.Context, id int32) ([]*dbSweep, error) | ||
|
||
// UpsertSweep inserts a sweep into the database, or updates an existing | ||
// sweep if it already exists. | ||
UpsertSweep(ctx context.Context, sweep *dbSweep) error | ||
|
||
// GetSweepStatus returns the completed status of the sweep. | ||
GetSweepStatus(ctx context.Context, swapHash lntypes.Hash) ( | ||
bool, error) | ||
GetSweepStatus(ctx context.Context, swapHash lntypes.Hash) (bool, error) | ||
|
||
// GetParentBatch returns the parent batch of a (completed) sweep. | ||
GetParentBatch(ctx context.Context, swapHash lntypes.Hash) ( | ||
*dbBatch, error) | ||
GetParentBatch(ctx context.Context, swapHash lntypes.Hash) (*dbBatch, | ||
error) | ||
|
||
// TotalSweptAmount returns the total amount swept by a (confirmed) | ||
// batch. | ||
|
@@ -135,7 +135,7 @@ type SpendNotifier struct { | |
} | ||
|
||
var ( | ||
ErrBatcherShuttingDown = fmt.Errorf("batcher shutting down") | ||
ErrBatcherShuttingDown = errors.New("batcher shutting down") | ||
) | ||
|
||
// Batcher is a system that is responsible for accepting sweep requests and | ||
|
@@ -153,6 +153,10 @@ type Batcher struct { | |
// quit signals that the batch must stop. | ||
quit chan struct{} | ||
|
||
// initDone is a channel that is closed when the batcher has been | ||
// initialized. | ||
initDone chan struct{} | ||
|
||
// wallet is the wallet kit client that is used by batches. | ||
wallet lndclient.WalletKitClient | ||
|
||
|
@@ -200,6 +204,7 @@ func NewBatcher(wallet lndclient.WalletKitClient, | |
sweepReqs: make(chan SweepRequest), | ||
errChan: make(chan error, 1), | ||
quit: make(chan struct{}), | ||
initDone: make(chan struct{}), | ||
wallet: wallet, | ||
chainNotifier: chainNotifier, | ||
signerClient: signerClient, | ||
|
@@ -216,6 +221,7 @@ func (b *Batcher) Run(ctx context.Context) error { | |
runCtx, cancel := context.WithCancel(ctx) | ||
defer func() { | ||
cancel() | ||
close(b.quit) | ||
|
||
for _, batch := range b.batches { | ||
batch.Wait() | ||
|
@@ -238,6 +244,9 @@ func (b *Batcher) Run(ctx context.Context) error { | |
} | ||
} | ||
|
||
// Signal that the batcher has been initialized. | ||
close(b.initDone) | ||
|
||
for { | ||
select { | ||
case sweepReq := <-b.sweepReqs: | ||
|
@@ -306,7 +315,7 @@ func (b *Batcher) handleSweep(ctx context.Context, sweep *sweep, | |
|
||
if batch.sweepExists(sweep.swapHash) { | ||
accepted, err := batch.addSweep(ctx, sweep) | ||
if err != nil { | ||
if err != nil && !errors.Is(err, ErrBatchShuttingDown) { | ||
return err | ||
} | ||
|
||
|
@@ -321,7 +330,7 @@ func (b *Batcher) handleSweep(ctx context.Context, sweep *sweep, | |
// If one of the batches accepts the sweep, we provide it to that batch. | ||
for _, batch := range b.batches { | ||
accepted, err := batch.addSweep(ctx, sweep) | ||
if err != nil && err != ErrBatchShuttingDown { | ||
if err != nil && !errors.Is(err, ErrBatchShuttingDown) { | ||
return err | ||
} | ||
|
||
|
@@ -379,6 +388,7 @@ func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) { | |
verifySchnorrSig: b.VerifySchnorrSig, | ||
purger: b.AddSweep, | ||
store: b.store, | ||
quit: b.quit, | ||
} | ||
|
||
batch := NewBatch(cfg, batchKit) | ||
|
@@ -407,23 +417,23 @@ func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) { | |
// spinUpBatchDB spins up a batch that already existed in storage, then | ||
// returns it. | ||
func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error { | ||
cfg := batchConfig{ | ||
maxTimeoutDistance: batch.cfg.maxTimeoutDistance, | ||
batchConfTarget: defaultBatchConfTarget, | ||
} | ||
|
||
rbfCache := rbfCache{ | ||
LastHeight: batch.rbfCache.LastHeight, | ||
FeeRate: batch.rbfCache.FeeRate, | ||
} | ||
|
||
dbSweeps, err := b.store.FetchBatchSweeps(ctx, batch.id) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(dbSweeps) == 0 { | ||
return fmt.Errorf("batch %d has no sweeps", batch.id) | ||
log.Infof("skipping restored batch %d as it has no sweeps", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe also delete from storage There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
batch.id) | ||
|
||
// It is safe to drop this empty batch as it has no sweeps. | ||
err := b.store.DropBatch(ctx, batch.id) | ||
if err != nil { | ||
log.Warnf("unable to drop empty batch %d: %v", | ||
batch.id, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
primarySweep := dbSweeps[0] | ||
|
@@ -439,6 +449,11 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error { | |
sweeps[sweep.swapHash] = *sweep | ||
} | ||
|
||
rbfCache := rbfCache{ | ||
LastHeight: batch.rbfCache.LastHeight, | ||
FeeRate: batch.rbfCache.FeeRate, | ||
} | ||
|
||
batchKit := batchKit{ | ||
id: batch.id, | ||
batchTxid: batch.batchTxid, | ||
|
@@ -456,6 +471,12 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error { | |
purger: b.AddSweep, | ||
store: b.store, | ||
log: batchPrefixLogger(fmt.Sprintf("%d", batch.id)), | ||
quit: b.quit, | ||
} | ||
|
||
cfg := batchConfig{ | ||
maxTimeoutDistance: batch.cfg.maxTimeoutDistance, | ||
batchConfTarget: defaultBatchConfTarget, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why setting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The source of confTarget is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We update this when the first sweep comes in, see here but agree it's basically a noop setting this here, as it's guaranteed it will be overwritten There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this is just a reorder, no added code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, ideally let's not introduce unwanted changes |
||
} | ||
|
||
newBatch := NewBatchFromDB(cfg, batchKit) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to add a check that the number of sweep in the batch is 0. If the batch is not empty, return an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, added!