mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
instantout: recheck reservation timing during recovery
Compare reservation expiry with the current height during recovery and use the HTLC path when the remaining window is too short.
This commit is contained in:
parent
adc181ea83
commit
cfbf74161b
3 changed files with 56 additions and 1 deletions
|
|
@ -63,6 +63,12 @@ type InitInstantOutCtx struct {
|
|||
sweepAddress btcutil.Address
|
||||
}
|
||||
|
||||
// RecoverInstantOutCtx contains the chain height at which an instant out is
|
||||
// resumed after restart.
|
||||
type RecoverInstantOutCtx struct {
|
||||
currentHeight int32
|
||||
}
|
||||
|
||||
// InitInstantOutAction is the first action that is executed when the instant
|
||||
// out FSM is started. It will send the instant out request to the server.
|
||||
func (f *FSM) InitInstantOutAction(ctx context.Context,
|
||||
|
|
@ -382,6 +388,26 @@ func (f *FSM) BuildHTLCAction(ctx context.Context,
|
|||
func (f *FSM) PushPreimageAction(ctx context.Context,
|
||||
eventCtx fsm.EventContext) fsm.EventType {
|
||||
|
||||
// A recovered swap may have been offline long enough that the server's
|
||||
// reservation timeout is now close. Fall back to the already finalized
|
||||
// HTLC instead of revealing the preimage without enough time to publish
|
||||
// that safety transaction.
|
||||
if recoverCtx, ok := eventCtx.(*RecoverInstantOutCtx); ok {
|
||||
minReservationExpiry := int64(recoverCtx.currentHeight) +
|
||||
int64(htlcExpiryDelta)
|
||||
for _, res := range f.InstantOut.Reservations {
|
||||
if int64(res.Expiry) >= minReservationExpiry {
|
||||
continue
|
||||
}
|
||||
|
||||
f.LastActionError = fmt.Errorf("reservation %x expires at "+
|
||||
"height %d, before recovery safety height %d",
|
||||
res.ID, res.Expiry, minReservationExpiry)
|
||||
|
||||
return OnErrorPublishHtlc
|
||||
}
|
||||
}
|
||||
|
||||
// First we'll create the musig2 context.
|
||||
coopSessions, coopClientNonces, err := f.InstantOut.createMusig2Session(
|
||||
ctx, f.cfg.Signer,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/instantout/reservation"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -113,3 +114,28 @@ func TestCleanupMuSig2Sessions(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, [][32]byte{firstID, secondID}, signer.cleaned)
|
||||
}
|
||||
|
||||
// TestPushPreimageRejectsExpiringReservation verifies that recovery takes the
|
||||
// on-chain fallback before revealing the preimage when a reservation is too
|
||||
// close to its server-controlled timeout.
|
||||
func TestPushPreimageRejectsExpiringReservation(t *testing.T) {
|
||||
instantOutFSM := &FSM{
|
||||
StateMachine: &fsm.StateMachine{},
|
||||
InstantOut: &InstantOut{
|
||||
Reservations: []*reservation.Reservation{
|
||||
{
|
||||
ID: reservation.ID{1},
|
||||
Expiry: 139,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
event := instantOutFSM.PushPreimageAction(
|
||||
t.Context(), &RecoverInstantOutCtx{currentHeight: 100},
|
||||
)
|
||||
require.Equal(t, OnErrorPublishHtlc, event)
|
||||
require.ErrorContains(
|
||||
t, instantOutFSM.LastActionError, "before recovery safety height",
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,8 +119,11 @@ func (m *Manager) recoverInstantOuts(ctx context.Context) error {
|
|||
|
||||
// As SendEvent can block, we'll start a goroutine to process
|
||||
// the event.
|
||||
recoverCtx := &RecoverInstantOutCtx{
|
||||
currentHeight: m.currentHeight,
|
||||
}
|
||||
go func() {
|
||||
err := instantOutFSM.SendEvent(ctx, OnRecover, nil)
|
||||
err := instantOutFSM.SendEvent(ctx, OnRecover, recoverCtx)
|
||||
if err != nil {
|
||||
log.Errorf("FSM %v Error sending recover "+
|
||||
"event %v, state: %v",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue