loop/staticaddr/loopin/interface.go
Slyghtning 6593afc8bc
staticaddr/loopin: recover risk-decision deadlines
Record replayed server risk decisions through the loop-in store,
recover accepted payment-deadline timers using the persisted decision
time, and handle persisted rejections on restart. This lets recovered
static loop-ins keep pending confirmation-risk state instead of
restarting payment timing from scratch.
2026-07-12 09:14:34 +02:00

146 lines
5.8 KiB
Go

package loopin
import (
"context"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/fsm"
"github.com/lightninglabs/loop/staticaddr/deposit"
"github.com/lightninglabs/loop/staticaddr/script"
"github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/zpay32"
)
const (
// DefaultLoopInOnChainCltvDelta is the time lock relative to current
// block height that swap server will accept on the swap initiation
// call.
DefaultLoopInOnChainCltvDelta = 1000
// DepositHtlcDelta is a safety buffer of blocks that needs to exist
// between the deposit expiry height and the htlc expiry height.
DepositHtlcDelta = 50
)
type (
// ValidateLoopInContract validates the contract parameters against our
// request.
ValidateLoopInContract func(height int32, htlcExpiry int32) error
)
// AddressManager handles fetching of address parameters.
type AddressManager interface {
// GetStaticAddressParameters returns the static address parameters.
GetStaticAddressParameters(ctx context.Context) (*script.Parameters,
error)
// GetStaticAddress returns the deposit address for the given client and
// server public keys.
GetStaticAddress(ctx context.Context) (*script.StaticAddress, error)
}
// DepositManager handles the interaction of loop-ins with deposits.
type DepositManager interface {
// EnsureDepositsFresh reconciles active deposits with the wallet view.
EnsureDepositsFresh(ctx context.Context) error
// GetAllDeposits returns all known deposits from the database store.
GetAllDeposits(ctx context.Context) ([]*deposit.Deposit, error)
// AllStringOutpointsActiveDeposits returns all deposits that have the
// given outpoints and are in the given state. If any of the outpoints
// does not correspond to an active deposit, the function returns false.
AllStringOutpointsActiveDeposits(outpoints []string,
stateFilter fsm.StateType) ([]*deposit.Deposit, bool)
// TransitionDeposits transitions the given deposits to the next state
// based on the given event. It returns an error if the transition is
// invalid.
TransitionDeposits(ctx context.Context, deposits []*deposit.Deposit,
event fsm.EventType, expectedFinalState fsm.StateType) error
// DepositsForOutpoints returns all deposits that behind the given
// outpoints. If ignoreUnknown is false, the function returns an error
// if any of the outpoints is not known, no error otherwise.
DepositsForOutpoints(ctx context.Context, outpoints []string,
ignoreUnknown bool) ([]*deposit.Deposit, error)
// GetActiveDepositsInState returns all active deposits in the given
// state.
GetActiveDepositsInState(stateFilter fsm.StateType) ([]*deposit.Deposit,
error)
}
// StaticAddressLoopInStore provides access to the static address loop-in DB.
type StaticAddressLoopInStore interface {
// CreateLoopIn creates a loop-in record in the database.
CreateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
// UpdateLoopIn updates a loop-in record in the database.
UpdateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
// GetStaticAddressLoopInSwapsByStates returns all loop-ins with given
// states.
GetStaticAddressLoopInSwapsByStates(ctx context.Context,
states []fsm.StateType) ([]*StaticAddressLoopIn, error)
// IsStored checks if the loop-in is already stored in the database.
IsStored(ctx context.Context, swapHash lntypes.Hash) (bool, error)
// RecordStaticAddressRiskDecision persists the server's
// confirmation-risk decision for the loop-in identified by swapHash.
RecordStaticAddressRiskDecision(ctx context.Context,
swapHash lntypes.Hash, decision ConfirmationRiskDecision) error
// GetLoopInByHash returns the loop-in swap with the given hash.
GetLoopInByHash(ctx context.Context, swapHash lntypes.Hash) (
*StaticAddressLoopIn, error)
// SwapHashesForDepositIDs returns a map of swap hashes to deposit IDs
// for the given deposit IDs.
SwapHashesForDepositIDs(ctx context.Context,
depositIDs []deposit.ID) (map[lntypes.Hash][]deposit.ID, error)
}
type QuoteGetter interface {
// GetLoopInQuote returns a quote for a loop-in swap.
GetLoopInQuote(ctx context.Context, amt btcutil.Amount,
pubKey route.Vertex, lastHop *route.Vertex,
routeHints [][]zpay32.HopHint, initiator string,
numDeposits uint32, fast bool) (*loop.LoopInQuote, error)
}
// TxOutChecker checks whether outpoints are still available in the chain
// backend's UTXO view.
type TxOutChecker interface {
// GetTxOuts returns entries for the requested outpoints that are
// available and unspent. Missing entries are unavailable or spent.
GetTxOuts(ctx context.Context, outpoints []wire.OutPoint) (
map[wire.OutPoint]*wire.TxOut, error)
}
type NotificationManager interface {
// SubscribeStaticLoopInSweepRequests subscribes to the static loop in
// sweep requests. These are sent by the server to the client to request
// a sweep of a static loop in that has been finished.
SubscribeStaticLoopInSweepRequests(ctx context.Context,
) <-chan *swapserverrpc.ServerStaticLoopInSweepNotification
// SubscribeStaticLoopInRiskAccepted subscribes to static loop in risk
// accepted notifications. These are sent by the server after the selected
// deposits are accepted by confirmation risk tracking.
SubscribeStaticLoopInRiskAccepted(
ctx context.Context, swapHash lntypes.Hash,
) <-chan *swapserverrpc.ServerStaticLoopInRiskAcceptedNotification
// SubscribeStaticLoopInRiskRejected subscribes to static loop in risk
// rejected notifications. These are sent by the server if it aborts the
// confirmation risk wait before payment.
SubscribeStaticLoopInRiskRejected(
ctx context.Context, swapHash lntypes.Hash,
) <-chan *swapserverrpc.ServerStaticLoopInRiskRejectedNotification
}