mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
loopd: abandon loop-ins
This commit is contained in:
parent
0fbf253391
commit
5e91c446b8
6 changed files with 161 additions and 3 deletions
53
loopin.go
53
loopin.go
|
|
@ -48,6 +48,10 @@ var (
|
|||
// TimeoutTxConfTarget defines the confirmation target for the loop in
|
||||
// timeout tx.
|
||||
TimeoutTxConfTarget = int32(2)
|
||||
|
||||
// ErrSwapFinalized is returned when a to be executed swap is already in
|
||||
// a final state.
|
||||
ErrSwapFinalized = errors.New("swap is in a final state")
|
||||
)
|
||||
|
||||
// loopInSwap contains all the in-memory state related to a pending loop in
|
||||
|
|
@ -70,6 +74,8 @@ type loopInSwap struct {
|
|||
|
||||
timeoutAddr btcutil.Address
|
||||
|
||||
abandonChan chan struct{}
|
||||
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +314,8 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
|
|||
swap.log.Infof("Server message: %v", swapResp.serverMessage)
|
||||
}
|
||||
|
||||
swap.abandonChan = make(chan struct{}, 1)
|
||||
|
||||
return &loopInInitResult{
|
||||
swap: swap,
|
||||
serverMessage: swapResp.serverMessage,
|
||||
|
|
@ -518,6 +526,11 @@ func (s *loopInSwap) execute(mainCtx context.Context,
|
|||
// error occurs.
|
||||
err = s.executeSwap(mainCtx)
|
||||
|
||||
// Stop the execution if the swap has been abandoned.
|
||||
if err != nil && s.state == loopdb.StateFailAbandoned {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanity check. If there is no error, the swap must be in a final
|
||||
// state.
|
||||
if err == nil && s.state.Type() == loopdb.StateTypePending {
|
||||
|
|
@ -553,6 +566,11 @@ func (s *loopInSwap) execute(mainCtx context.Context,
|
|||
func (s *loopInSwap) executeSwap(globalCtx context.Context) error {
|
||||
var err error
|
||||
|
||||
// If the swap is already in a final state, we can return immediately.
|
||||
if s.state.IsFinal() {
|
||||
return ErrSwapFinalized
|
||||
}
|
||||
|
||||
// For loop in, the client takes the first step by publishing the
|
||||
// on-chain htlc. Only do this if we haven't already done so in a
|
||||
// previous run.
|
||||
|
|
@ -688,6 +706,11 @@ func (s *loopInSwap) waitForHtlcConf(globalCtx context.Context) (
|
|||
case notification := <-s.blockEpochChan:
|
||||
s.height = notification.(int32)
|
||||
|
||||
// If the client requested the swap to be abandoned, we override
|
||||
// the status in the database.
|
||||
case <-s.abandonChan:
|
||||
return nil, s.setStateAbandoned(ctx)
|
||||
|
||||
// Cancel.
|
||||
case <-globalCtx.Done():
|
||||
return nil, globalCtx.Err()
|
||||
|
|
@ -840,6 +863,11 @@ func (s *loopInSwap) waitForSwapComplete(ctx context.Context,
|
|||
htlcKeyRevealed := false
|
||||
for !htlcSpend || !invoiceFinalized {
|
||||
select {
|
||||
// If the client requested the swap to be abandoned, we override
|
||||
// the status in the database.
|
||||
case <-s.abandonChan:
|
||||
return s.setStateAbandoned(ctx)
|
||||
|
||||
// Spend notification error.
|
||||
case err := <-spendErr:
|
||||
return err
|
||||
|
|
@ -1062,6 +1090,31 @@ func (s *loopInSwap) publishTimeoutTx(ctx context.Context,
|
|||
return fee, nil
|
||||
}
|
||||
|
||||
// setStateAbandoned stores the abandoned state and announces it. It also
|
||||
// cancels the swap invoice so the server can't settle it.
|
||||
func (s *loopInSwap) setStateAbandoned(ctx context.Context) error {
|
||||
s.log.Infof("Abandoning swap %v...", s.hash)
|
||||
|
||||
if !s.state.IsPending() {
|
||||
return fmt.Errorf("cannot abandon swap in state %v", s.state)
|
||||
}
|
||||
|
||||
s.setState(loopdb.StateFailAbandoned)
|
||||
|
||||
err := s.persistAndAnnounceState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the invoice is already settled or canceled, this is a nop.
|
||||
_ = s.lnd.Invoices.CancelInvoice(ctx, s.hash)
|
||||
|
||||
return fmt.Errorf("swap hash "+
|
||||
"abandoned by client, "+
|
||||
"swap ID: %v, %v",
|
||||
s.hash, err)
|
||||
}
|
||||
|
||||
// persistAndAnnounceState updates the swap state on disk and sends out an
|
||||
// update notification.
|
||||
func (s *loopInSwap) persistAndAnnounceState(ctx context.Context) error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue