@@ -271,14 +271,6 @@ type addSweepsRequest struct {
271
271
// Notifier is a notifier that is used to notify the requester of this
272
272
// sweep that the sweep was successful.
273
273
notifier * SpendNotifier
274
-
275
- // completed is set if the sweep is spent and the spending transaction
276
- // is reorg-safely confirmed.
277
- completed bool
278
-
279
- // parentBatch is the parent batch of this sweep. It is loaded ony if
280
- // completed is true.
281
- parentBatch * dbBatch
282
274
}
283
275
284
276
// SpendDetail is a notification that is send to the user of sweepbatcher when
@@ -687,10 +679,7 @@ func (b *Batcher) Run(ctx context.Context) error {
687
679
for {
688
680
select {
689
681
case req := <- b .addSweepsChan :
690
- err = b .handleSweeps (
691
- runCtx , req .sweeps , req .notifier , req .completed ,
692
- req .parentBatch ,
693
- )
682
+ err = b .handleSweeps (runCtx , req .sweeps , req .notifier )
694
683
if err != nil {
695
684
warnf ("handleSweeps failed: %v." , err )
696
685
@@ -803,15 +792,12 @@ func (b *Batcher) AddSweep(ctx context.Context, sweepReq *SweepRequest) error {
803
792
return fmt .Errorf ("failed to get the status of sweep %v: %w" ,
804
793
sweep .outpoint , err )
805
794
}
806
- var (
807
- parentBatch * dbBatch
808
- fullyConfirmed bool
809
- )
795
+ var fullyConfirmed bool
810
796
if completed {
811
797
// Verify that the parent batch is confirmed. Note that a batch
812
798
// is only considered confirmed after it has received three
813
799
// on-chain confirmations to prevent issues caused by reorgs.
814
- parentBatch , err = b .store .GetParentBatch (ctx , sweep .outpoint )
800
+ parentBatch , err : = b .store .GetParentBatch (ctx , sweep .outpoint )
815
801
if err != nil {
816
802
return fmt .Errorf ("unable to get parent batch for " +
817
803
"sweep %x: %w" , sweep .swapHash [:6 ], err )
@@ -847,10 +833,8 @@ func (b *Batcher) AddSweep(ctx context.Context, sweepReq *SweepRequest) error {
847
833
sweep .swapHash [:6 ], sweep .presigned , completed )
848
834
849
835
req := & addSweepsRequest {
850
- sweeps : sweeps ,
851
- notifier : sweepReq .Notifier ,
852
- completed : completed ,
853
- parentBatch : parentBatch ,
836
+ sweeps : sweeps ,
837
+ notifier : sweepReq .Notifier ,
854
838
}
855
839
856
840
select {
@@ -895,33 +879,17 @@ func (b *Batcher) testRunInEventLoop(ctx context.Context, handler func()) {
895
879
// handleSweeps handles a sweep request by either placing the group of sweeps in
896
880
// an existing batch, or by spinning up a new batch for it.
897
881
func (b * Batcher ) handleSweeps (ctx context.Context , sweeps []* sweep ,
898
- notifier * SpendNotifier , completed bool , parentBatch * dbBatch ) error {
882
+ notifier * SpendNotifier ) error {
899
883
900
884
// Since the whole group is added to the same batch and belongs to
901
885
// the same transaction, we use sweeps[0] below where we need any sweep.
902
886
sweep := sweeps [0 ]
903
887
904
- // If the sweep has already been completed in a confirmed batch then we
905
- // can't attach its notifier to the batch as that is no longer running.
906
- // Instead we directly detect and return the spend here.
907
- if completed && parentBatch .Confirmed {
908
- return b .monitorSpendAndNotify (
909
- ctx , sweeps , parentBatch .ID , notifier ,
910
- )
911
- }
912
-
913
888
sweep .notifier = notifier
914
889
915
- // This is a check to see if a batch is completed. In that case we just
916
- // lazily delete it.
917
- for _ , batch := range b .batches {
918
- if batch .isComplete () {
919
- delete (b .batches , batch .id )
920
- }
921
- }
922
-
923
890
// Check if the sweep is already in a batch. If that is the case, we
924
891
// provide the sweep to that batch and return.
892
+ readded := false
925
893
for _ , batch := range b .batches {
926
894
if batch .sweepExists (sweep .outpoint ) {
927
895
accepted , err := batch .addSweeps (ctx , sweeps )
@@ -936,12 +904,72 @@ func (b *Batcher) handleSweeps(ctx context.Context, sweeps []*sweep,
936
904
}
937
905
938
906
// The sweep was updated in the batch, our job is done.
939
- return nil
907
+ readded = true
908
+ break
909
+ }
910
+ }
911
+
912
+ // Check whether any batch is already completed and lazily delete it. Do
913
+ // this after attempting the re-add so we do not remove the batch that
914
+ // would have accepted the sweep again; otherwise we could miss the
915
+ // re-addition and spin up a new batch for an already finished sweep.
916
+ for _ , batch := range b .batches {
917
+ if batch .isComplete () {
918
+ delete (b .batches , batch .id )
919
+ }
920
+ }
921
+
922
+ // If the batch was re-added to an existing batch, our job is done.
923
+ if readded {
924
+ return nil
925
+ }
926
+
927
+ // If the sweep has already been completed in a confirmed batch then we
928
+ // can't attach its notifier to the batch as that is no longer running.
929
+ // Instead we directly detect and return the spend here. We cannot reuse
930
+ // the values gathered in AddSweep because the sweep status may change in
931
+ // the meantime. If the status flips while handleSweeps is running, the
932
+ // re-add path above will handle it. A batch is removed from b.batches
933
+ // only after the code below finds the sweep fully confirmed and switches
934
+ // to the monitorSpendAndNotify path.
935
+ completed , err := b .store .GetSweepStatus (ctx , sweep .outpoint )
936
+ if err != nil {
937
+ return fmt .Errorf ("failed to get the status of sweep %v: %w" ,
938
+ sweep .outpoint , err )
939
+ }
940
+ debugf ("Status of the sweep group of %d sweeps with primarySweep %x: " +
941
+ "presigned=%v, fully_confirmed=%v" , len (sweeps ),
942
+ sweep .swapHash [:6 ], sweep .presigned , completed )
943
+ if completed {
944
+ // Verify that the parent batch is confirmed. Note that a batch
945
+ // is only considered confirmed after it has received three
946
+ // on-chain confirmations to prevent issues caused by reorgs.
947
+ parentBatch , err := b .store .GetParentBatch (ctx , sweep .outpoint )
948
+ if err != nil {
949
+ return fmt .Errorf ("unable to get parent batch for " +
950
+ "sweep %x: %w" , sweep .swapHash [:6 ], err )
951
+ }
952
+
953
+ debugf ("Status of the parent batch of the sweep group of %d " +
954
+ "sweeps with primarySweep %x: confirmed=%v" ,
955
+ len (sweeps ), sweep .swapHash [:6 ], parentBatch .Confirmed )
956
+
957
+ // Note that sweeps are marked completed after the batch is
958
+ // marked confirmed because here we check the sweep status
959
+ // first and then check the batch status.
960
+ if parentBatch .Confirmed {
961
+ debugf ("Sweep group of %d sweeps with primarySweep %x " +
962
+ "is fully confirmed, switching directly to " +
963
+ "monitoring" , len (sweeps ), sweep .swapHash [:6 ])
964
+
965
+ return b .monitorSpendAndNotify (
966
+ ctx , sweeps , parentBatch .ID , notifier ,
967
+ )
940
968
}
941
969
}
942
970
943
971
// Try to run the greedy algorithm of batch selection to minimize costs.
944
- err : = b .greedyAddSweeps (ctx , sweeps )
972
+ err = b .greedyAddSweeps (ctx , sweeps )
945
973
if err == nil {
946
974
// The greedy algorithm succeeded.
947
975
return nil
0 commit comments