Skip to content

Commit b9eb942

Browse files
committed
staticaddr: deposit changes to be squashed
These deposit changes will be squashed into the original commits once merged into staging.
1 parent 6ddc03c commit b9eb942

File tree

5 files changed

+259
-89
lines changed

5 files changed

+259
-89
lines changed

staticaddr/deposit/actions.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (f *FSM) PublishDepositExpirySweepAction(_ fsm.EventContext) fsm.EventType
4040
)
4141
if err != nil {
4242
return f.HandleError(fmt.Errorf("timeout sweep fee "+
43-
"estimation failed: %v", err))
43+
"estimation failed: %w", err))
4444
}
4545

4646
weight := script.ExpirySpendWeight()
@@ -95,7 +95,7 @@ func (f *FSM) PublishDepositExpirySweepAction(_ fsm.EventContext) fsm.EventType
9595
err = f.cfg.WalletKit.PublishTransaction(f.ctx, msgTx, txLabel)
9696
if err != nil {
9797
if !strings.Contains(err.Error(), "output already spent") {
98-
log.Errorf("%v: %v", txLabel, err)
98+
log.Errorf("%v: %w", txLabel, err)
9999
f.LastActionError = err
100100
return fsm.OnError
101101
}
@@ -120,7 +120,7 @@ func (f *FSM) WaitForExpirySweepAction(_ fsm.EventContext) fsm.EventType {
120120

121121
select {
122122
case err := <-errSpendChan:
123-
log.Debugf("error while sweeping expired deposit: %v", err)
123+
log.Debugf("error while sweeping expired deposit: %w", err)
124124
return fsm.OnError
125125

126126
case confirmedTx := <-spendChan:
@@ -148,9 +148,9 @@ func (f *FSM) SweptExpiredDepositAction(_ fsm.EventContext) fsm.EventType {
148148
return fsm.NoOp
149149
}
150150

151-
// WithdrawnDepositAction is the final action after a withdrawal. It signals to
151+
// FinalizeDepositAction is the final action after a withdrawal. It signals to
152152
// the manager that the deposit has been swept and the FSM can be removed.
153-
func (f *FSM) WithdrawnDepositAction(_ fsm.EventContext) fsm.EventType {
153+
func (f *FSM) FinalizeDepositAction(_ fsm.EventContext) fsm.EventType {
154154
select {
155155
case <-f.ctx.Done():
156156
return fsm.OnError

staticaddr/deposit/deposit.go

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,47 +59,26 @@ type Deposit struct {
5959
sync.Mutex
6060
}
6161

62-
// IsInPendingState returns true if the deposit is pending.
63-
func (d *Deposit) IsInPendingState() bool {
64-
d.Lock()
65-
defer d.Unlock()
66-
67-
return !d.IsInFinalState()
68-
}
69-
7062
// IsInFinalState returns true if the deposit is final.
7163
func (d *Deposit) IsInFinalState() bool {
72-
d.Lock()
73-
defer d.Unlock()
74-
75-
return d.state == Expired || d.state == Withdrawn || d.state == Failed
64+
return d.state == Expired || d.state == Withdrawn ||
65+
d.state == Failed || d.state == LoopedIn ||
66+
d.state == HtlcTimeoutSwept
7667
}
7768

7869
func (d *Deposit) IsExpired(currentHeight, expiry uint32) bool {
79-
d.Lock()
80-
defer d.Unlock()
81-
8270
return currentHeight >= uint32(d.ConfirmationHeight)+expiry
8371
}
8472

8573
func (d *Deposit) GetState() fsm.StateType {
86-
d.Lock()
87-
defer d.Unlock()
88-
8974
return d.state
9075
}
9176

9277
func (d *Deposit) SetState(state fsm.StateType) {
93-
d.Lock()
94-
defer d.Unlock()
95-
9678
d.state = state
9779
}
9880

9981
func (d *Deposit) IsInState(state fsm.StateType) bool {
100-
d.Lock()
101-
defer d.Unlock()
102-
10382
return d.state == state
10483
}
10584

staticaddr/deposit/fsm.go

Lines changed: 142 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,95 @@ var (
2727

2828
// States.
2929
var (
30+
// Deposited signals that funds at a static address have reached the
31+
// confirmation height.
3032
Deposited = fsm.StateType("Deposited")
3133

34+
// Withdrawing signals that the withdrawal transaction has been
35+
// broadcast, awaiting sufficient confirmations.
3236
Withdrawing = fsm.StateType("Withdrawing")
3337

38+
// Withdrawn signals that the withdrawal transaction has been confirmed.
3439
Withdrawn = fsm.StateType("Withdrawn")
3540

41+
// LoopingIn signals that the deposit is locked for a loop in swap.
42+
LoopingIn = fsm.StateType("LoopingIn")
43+
44+
// LoopedIn signals that the loop in swap has been successfully
45+
// completed. It implies that we signed the sweepless sweep tx for the
46+
// server.
47+
LoopedIn = fsm.StateType("LoopedIn")
48+
49+
// SweepHtlcTimeout signals that the htlc timeout path is in the
50+
// process of being swept.
51+
SweepHtlcTimeout = fsm.StateType("SweepHtlcTimeout")
52+
53+
// HtlcTimeoutSwept signals that the htlc timeout path has been swept.
54+
HtlcTimeoutSwept = fsm.StateType("HtlcTimeoutSwept")
55+
56+
// PublishExpiredDeposit signals that the deposit has expired and we are
57+
// in the process of publishing the expiry sweep transaction.
3658
PublishExpiredDeposit = fsm.StateType("PublishExpiredDeposit")
3759

60+
// WaitForExpirySweep signals that the expiry sweep transaction has been
61+
// published and we are waiting for it to be confirmed.
3862
WaitForExpirySweep = fsm.StateType("WaitForExpirySweep")
3963

64+
// Expired signals that the deposit has expired and the expiry sweep
65+
// transaction has been confirmed sufficiently.
4066
Expired = fsm.StateType("Expired")
4167

68+
// Failed signals that the deposit has neither been withdrawn nor looped
69+
// in, but expired.
4270
Failed = fsm.StateType("Failed")
4371
)
4472

4573
// Events.
4674
var (
47-
OnStart = fsm.EventType("OnStart")
75+
// OnStart is sent to the fsm once the deposit outpoint has been
76+
// sufficiently confirmed. It transitions the fsm into the Deposited
77+
// state from where we can trigger a withdrawal, a loopin or an expiry.
78+
OnStart = fsm.EventType("OnStart")
79+
80+
// OnWithdrawInitiated is sent to the fsm when a withdrawal has been
81+
// initiated.
4882
OnWithdrawInitiated = fsm.EventType("OnWithdrawInitiated")
49-
OnWithdrawn = fsm.EventType("OnWithdrawn")
50-
OnExpiry = fsm.EventType("OnExpiry")
51-
OnExpiryPublished = fsm.EventType("OnExpiryPublished")
52-
OnExpirySwept = fsm.EventType("OnExpirySwept")
53-
OnRecover = fsm.EventType("OnRecover")
83+
84+
// OnWithdrawn is sent to the fsm when a withdrawal has been confirmed.
85+
OnWithdrawn = fsm.EventType("OnWithdrawn")
86+
87+
// OnLoopinInitiated is sent to the fsm when a loop in has been
88+
// initiated.
89+
OnLoopinInitiated = fsm.EventType("OnLoopinInitiated")
90+
91+
// OnSweepingHtlcTimeout is sent to the fsm when the htlc timeout path
92+
// is being swept. This indicates that the server didn't pay the swap
93+
// invoice, but the htlc tx was published, from we which we need to
94+
// sweep the htlc timeout path.
95+
OnSweepingHtlcTimeout = fsm.EventType("OnSweepingHtlcTimeout")
96+
97+
// OnHtlcTimeoutSwept is sent to the fsm when the htlc timeout path has
98+
// been swept.
99+
OnHtlcTimeoutSwept = fsm.EventType("OnHtlcTimeoutSwept")
100+
101+
// OnLoopedIn is sent to the fsm when the user intents to use the
102+
// deposit for a loop in swap.
103+
OnLoopedIn = fsm.EventType("OnLoopedIn")
104+
105+
// OnExpiry is sent to the fsm when the deposit has expired.
106+
OnExpiry = fsm.EventType("OnExpiry")
107+
108+
// OnExpiryPublished is sent to the fsm when the expiry sweep tx has
109+
// been published.
110+
OnExpiryPublished = fsm.EventType("OnExpiryPublished")
111+
112+
// OnExpirySwept is sent to the fsm when the expiry sweep tx has been
113+
// confirmed.
114+
OnExpirySwept = fsm.EventType("OnExpirySwept")
115+
116+
// OnRecover is sent to the fsm when it should recover from client
117+
// restart.
118+
OnRecover = fsm.EventType("OnRecover")
54119
)
55120

56121
// FSM is the state machine that handles the instant out.
@@ -81,12 +146,12 @@ func NewFSM(ctx context.Context, deposit *Deposit, cfg *ManagerConfig,
81146
params, err := cfg.AddressManager.GetStaticAddressParameters(ctx)
82147
if err != nil {
83148
return nil, fmt.Errorf("unable to get static address "+
84-
"parameters: %v", err)
149+
"parameters: %w", err)
85150
}
86151

87152
address, err := cfg.AddressManager.GetStaticAddress(ctx)
88153
if err != nil {
89-
return nil, fmt.Errorf("unable to get static address: %v", err)
154+
return nil, fmt.Errorf("unable to get static address: %w", err)
90155
}
91156

92157
depoFsm := &FSM{
@@ -149,7 +214,7 @@ func (f *FSM) handleBlockNotification(currentHeight uint32) {
149214
err := f.SendEvent(OnExpiry, nil)
150215
if err != nil {
151216
log.Debugf("error sending OnExpiry "+
152-
"event: %v", err)
217+
"event: %w", err)
153218
}
154219
}()
155220
}
@@ -169,6 +234,7 @@ func (f *FSM) DepositStatesV0() fsm.States {
169234
Transitions: fsm.Transitions{
170235
OnExpiry: PublishExpiredDeposit,
171236
OnWithdrawInitiated: Withdrawing,
237+
OnLoopinInitiated: LoopingIn,
172238
OnRecover: Deposited,
173239
},
174240
Action: fsm.NoOpAction,
@@ -228,11 +294,55 @@ func (f *FSM) DepositStatesV0() fsm.States {
228294
},
229295
Action: fsm.NoOpAction,
230296
},
297+
LoopingIn: fsm.State{
298+
Transitions: fsm.Transitions{
299+
// This event is triggered when the loop in
300+
// payment has been received. We consider the
301+
// swap to be completed and transition to a
302+
// final state.
303+
OnLoopedIn: LoopedIn,
304+
305+
// If the deposit expires while the loop in is
306+
// still pending, we publish the expiry sweep.
307+
OnExpiry: PublishExpiredDeposit,
308+
309+
// We encounter this signal if the server
310+
// published the htlc tx without paying us. We
311+
// then need to monitor for the timeout path to
312+
// open up to sweep it.
313+
OnSweepingHtlcTimeout: SweepHtlcTimeout,
314+
315+
OnLoopinInitiated: LoopingIn,
316+
317+
OnRecover: LoopingIn,
318+
fsm.OnError: Deposited,
319+
},
320+
Action: fsm.NoOpAction,
321+
},
322+
LoopedIn: fsm.State{
323+
Transitions: fsm.Transitions{
324+
OnExpiry: Expired,
325+
},
326+
Action: f.FinalizeDepositAction,
327+
},
328+
SweepHtlcTimeout: fsm.State{
329+
Transitions: fsm.Transitions{
330+
OnHtlcTimeoutSwept: HtlcTimeoutSwept,
331+
OnRecover: SweepHtlcTimeout,
332+
},
333+
Action: fsm.NoOpAction,
334+
},
335+
HtlcTimeoutSwept: fsm.State{
336+
Transitions: fsm.Transitions{
337+
OnExpiry: HtlcTimeoutSwept,
338+
},
339+
Action: f.FinalizeDepositAction,
340+
},
231341
Withdrawn: fsm.State{
232342
Transitions: fsm.Transitions{
233343
OnExpiry: Expired,
234344
},
235-
Action: f.WithdrawnDepositAction,
345+
Action: f.FinalizeDepositAction,
236346
},
237347
Failed: fsm.State{
238348
Transitions: fsm.Transitions{
@@ -256,24 +366,36 @@ func (f *FSM) updateDeposit(notification fsm.Notification) {
256366
)
257367

258368
f.deposit.SetState(notification.NextState)
259-
260-
// Don't update the deposit if we are in an initial state or if we
261-
// are transitioning from an initial state to a failed state.
262-
d := f.deposit
263-
if d.IsInState(fsm.EmptyState) || d.IsInState(Deposited) ||
264-
(notification.PreviousState == Deposited && d.IsInState(
265-
Failed,
266-
)) {
267-
369+
if skipUpdate(notification, f.deposit) {
268370
return
269371
}
270372

271373
err := f.cfg.Store.UpdateDeposit(f.ctx, f.deposit)
272374
if err != nil {
273-
f.Errorf("unable to update deposit: %v", err)
375+
f.Errorf("unable to update deposit: %w", err)
274376
}
275377
}
276378

379+
// skipUpdate returns true if the deposit should not be updated for the given
380+
// notification.
381+
func skipUpdate(notification fsm.Notification, d *Deposit) bool {
382+
prevState := notification.PreviousState
383+
384+
// Don't update the deposit if we are in an initial state or if we are
385+
// transitioning from an initial state to a failed state.
386+
if d.IsInState(fsm.EmptyState) || d.IsInState(Deposited) &&
387+
prevState == fsm.EmptyState ||
388+
d.IsInState(prevState) ||
389+
prevState == Deposited && d.IsInState(Deposited) ||
390+
prevState == Deposited && d.IsInState(Failed) ||
391+
prevState == LoopingIn && d.IsInState(LoopingIn) {
392+
393+
return true
394+
}
395+
396+
return false
397+
}
398+
277399
// Infof logs an info message with the deposit outpoint.
278400
func (f *FSM) Infof(format string, args ...interface{}) {
279401
log.Infof(

0 commit comments

Comments
 (0)