mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
staticaddr/deposit: ignore expiry blocks in final states
Return early when block notifications reach deposits that already moved into a terminal state. This prevents final deposits from retrying expiry handling after recovery or while their FSM is still draining block updates.
This commit is contained in:
parent
ba1c37c0da
commit
0611832030
2 changed files with 64 additions and 0 deletions
|
|
@ -241,6 +241,10 @@ func NewFSM(ctx context.Context, deposit *Deposit, cfg *ManagerConfig,
|
|||
func (f *FSM) handleBlockNotification(ctx context.Context,
|
||||
currentHeight uint32) {
|
||||
|
||||
if f.deposit.IsInFinalState() {
|
||||
return
|
||||
}
|
||||
|
||||
// If the deposit is expired but not yet sufficiently confirmed, we
|
||||
// republish the expiry sweep transaction.
|
||||
if f.deposit.IsExpired(currentHeight, f.params.Expiry) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package deposit
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
|
|
@ -11,6 +12,65 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestHandleBlockNotificationIgnoresFinalStates verifies that a block-driven
|
||||
// expiry notification cannot mutate deposits that already reached a final
|
||||
// state but have not yet been removed from the manager's active set.
|
||||
func TestHandleBlockNotificationIgnoresFinalStates(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
finalStates := []fsm.StateType{
|
||||
Expired,
|
||||
Withdrawn,
|
||||
LoopedIn,
|
||||
HtlcTimeoutSwept,
|
||||
ChannelPublished,
|
||||
}
|
||||
|
||||
for i, state := range finalStates {
|
||||
t.Run(string(state), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
outpoint := wire.OutPoint{
|
||||
Hash: chainhash.Hash{byte(i + 1)},
|
||||
Index: uint32(i),
|
||||
}
|
||||
deposit := &Deposit{
|
||||
OutPoint: outpoint,
|
||||
ConfirmationHeight: 1,
|
||||
}
|
||||
deposit.SetState(state)
|
||||
|
||||
depositFSM := &FSM{
|
||||
cfg: &ManagerConfig{
|
||||
Store: new(mockStore),
|
||||
},
|
||||
deposit: deposit,
|
||||
params: &script.Parameters{Expiry: 1},
|
||||
quitChan: make(chan struct{}),
|
||||
finalizedDepositChan: make(chan wire.OutPoint, 1),
|
||||
}
|
||||
depositFSM.StateMachine = fsm.NewStateMachineWithState(
|
||||
depositFSM.DepositStatesV0(), state,
|
||||
DefaultObserverSize,
|
||||
)
|
||||
depositFSM.ActionEntryFunc = depositFSM.updateDeposit
|
||||
|
||||
depositFSM.handleBlockNotification(t.Context(), 3)
|
||||
|
||||
require.Never(t, func() bool {
|
||||
return deposit.GetState() != state
|
||||
}, 100*time.Millisecond, 10*time.Millisecond)
|
||||
|
||||
select {
|
||||
case finalized := <-depositFSM.finalizedDepositChan:
|
||||
t.Fatalf("unexpected finalization for %v", finalized)
|
||||
|
||||
default:
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoopingInTransitionsToSweepHtlcTimeout verifies that a deposit selected
|
||||
// by a loop-in can be moved into the timeout sweep state if the server confirms
|
||||
// the HTLC without paying the invoice.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue