staticaddr/deposit: handle loop-in htlc timeout

Keep deposits locked when the server publishes the loop-in HTLC
without paying the invoice.

This lets the client sweep through the HTLC timeout path instead
of making the same outputs available for another action.
This commit is contained in:
Slyghtning 2026-07-01 07:15:03 +02:00
parent eea3f96ada
commit ba1c37c0da
No known key found for this signature in database
GPG key ID: F82D456EA023C9BF
2 changed files with 57 additions and 0 deletions

View file

@ -353,6 +353,11 @@ func (f *FSM) DepositStatesV0() fsm.States {
// still pending, we publish the expiry sweep.
OnExpiry: PublishExpirySweep,
// If the server publishes the HTLC without
// paying us, we need to keep the deposit locked
// until the HTLC timeout path can be swept.
OnSweepingHtlcTimeout: SweepHtlcTimeout,
OnLoopInInitiated: LoopingIn,
OnRecover: LoopingIn,

View file

@ -0,0 +1,52 @@
package deposit
import (
"testing"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/loop/fsm"
"github.com/lightninglabs/loop/staticaddr/script"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
// 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.
func TestLoopingInTransitionsToSweepHtlcTimeout(t *testing.T) {
t.Parallel()
outpoint := wire.OutPoint{
Hash: chainhash.Hash{9},
Index: 9,
}
deposit := &Deposit{
OutPoint: outpoint,
}
deposit.SetState(LoopingIn)
store := new(mockStore)
store.On(
"UpdateDeposit", mock.Anything, mock.Anything,
).Return(nil).Once()
depositFSM := &FSM{
cfg: &ManagerConfig{
Store: store,
},
deposit: deposit,
params: &script.Parameters{Expiry: 1},
}
depositFSM.StateMachine = fsm.NewStateMachineWithState(
depositFSM.DepositStatesV0(), LoopingIn, DefaultObserverSize,
)
depositFSM.ActionEntryFunc = depositFSM.updateDeposit
err := depositFSM.SendEvent(
t.Context(), OnSweepingHtlcTimeout, nil,
)
require.NoError(t, err)
require.Equal(t, SweepHtlcTimeout, deposit.GetState())
store.AssertExpectations(t)
}