@@ -17,6 +17,7 @@ import (
1717 "github.com/lightninglabs/loop/loopdb"
1818 "github.com/lightninglabs/loop/swap"
1919 "github.com/lightninglabs/loop/sweep"
20+ "github.com/lightningnetwork/lnd/lntypes"
2021 "github.com/lightningnetwork/lnd/routing/route"
2122 "google.golang.org/grpc/status"
2223)
@@ -68,6 +69,11 @@ type Client struct {
6869 started uint32 // To be used atomically.
6970 errChan chan error
7071
72+ // abandonChans allows for accessing a swap's abandon channel by
73+ // providing its swap hash. This map is used to look up the abandon
74+ // channel of a swap if the client requests to abandon it.
75+ abandonChans map [lntypes.Hash ]chan struct {}
76+
7177 lndServices * lndclient.LndServices
7278 sweeper * sweep.Sweeper
7379 executor * executor
@@ -179,6 +185,7 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
179185 sweeper : sweeper ,
180186 executor : executor ,
181187 resumeReady : make (chan struct {}),
188+ abandonChans : make (map [lntypes.Hash ]chan struct {}),
182189 }
183190
184191 cleanup := func () {
@@ -317,10 +324,10 @@ func (s *Client) Run(ctx context.Context, statusChan chan<- SwapInfo) error {
317324 }()
318325
319326 // Main event loop.
320- err = s .executor .run (mainCtx , statusChan )
327+ err = s .executor .run (mainCtx , statusChan , s . abandonChans )
321328
322329 // Consider canceled as happy flow.
323- if err == context .Canceled {
330+ if errors . Is ( err , context .Canceled ) {
324331 err = nil
325332 }
326333
@@ -374,6 +381,12 @@ func (s *Client) resumeSwaps(ctx context.Context,
374381 continue
375382 }
376383
384+ // Store the swap's abandon channel so that the client can
385+ // abandon the swap by providing the swap hash.
386+ s .executor .Lock ()
387+ s .abandonChans [swap .hash ] = swap .abandonChan
388+ s .executor .Unlock ()
389+
377390 s .executor .initiateSwap (ctx , swap )
378391 }
379392}
@@ -578,6 +591,10 @@ func (s *Client) LoopIn(globalCtx context.Context,
578591 }
579592 swap := initResult .swap
580593
594+ s .executor .Lock ()
595+ s .abandonChans [swap .hash ] = swap .abandonChan
596+ s .executor .Unlock ()
597+
581598 // Post swap to the main loop.
582599 s .executor .initiateSwap (globalCtx , swap )
583600
@@ -753,3 +770,26 @@ func (s *Client) Probe(ctx context.Context, req *ProbeRequest) error {
753770 req .RouteHints ,
754771 )
755772}
773+
774+ // AbandonSwap sends a signal on the abandon channel of the swap identified by
775+ // the passed swap hash. This will cause the swap to abandon itself.
776+ func (s * Client ) AbandonSwap (ctx context.Context ,
777+ req * AbandonSwapRequest ) error {
778+
779+ if req == nil {
780+ return errors .New ("no request provided" )
781+ }
782+
783+ s .executor .Lock ()
784+ defer s .executor .Unlock ()
785+
786+ select {
787+ case s .abandonChans [req .SwapHash ] <- struct {}{}:
788+ case <- ctx .Done ():
789+ return ctx .Err ()
790+ default :
791+ // This is to avoid writing to a full channel.
792+ }
793+
794+ return nil
795+ }
0 commit comments