From 51258af02572a9f201a69994f9b2b40c5dc68ca1 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Wed, 1 Oct 2025 08:49:32 +0200 Subject: [PATCH] staticaddr: fast-flag support --fast allows the client to expedite the publishing of on-chain swap transactions with change, e.g. if --amount was specified. --- interface.go | 11 +++++++++++ staticaddr/loopin/actions.go | 1 + staticaddr/loopin/interface.go | 4 ++-- staticaddr/loopin/loopin.go | 4 ++++ staticaddr/loopin/manager.go | 7 ++++--- staticaddr/loopin/sql_store.go | 2 ++ 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/interface.go b/interface.go index 1ca1fda3..67b9f831 100644 --- a/interface.go +++ b/interface.go @@ -343,6 +343,11 @@ type StaticAddressLoopInRequest struct { // the user did not select an amount, the amount of the selected // deposits is used. SelectedAmount btcutil.Amount + + // Fast indicates whether the user requested a fast static loop-in. If + // set, the flag is passed to the server which may alter its behavior + // (for example, publish sooner) and is stored in the database. + Fast bool } // LoopInTerms are the server terms on which it executes loop in swaps. @@ -405,6 +410,12 @@ type LoopInQuoteRequest struct { // per-input service fee. This is to cover for the increased on-chain // fee the server has to pay when the sweeping transaction is broadcast. NumDeposits uint32 + + // Fast indicates whether the user requested a fast static loop-in + // publication on-chain. This is helpful if swap change needs to get + // confirmed fast. This comes at a higher swap cost since the server has + // to pay more on-chain fees. + Fast bool } // LoopInQuote contains estimates for the fees making up the total swap cost diff --git a/staticaddr/loopin/actions.go b/staticaddr/loopin/actions.go index 1cd7d509..bf896330 100644 --- a/staticaddr/loopin/actions.go +++ b/staticaddr/loopin/actions.go @@ -135,6 +135,7 @@ func (f *FSM) InitHtlcAction(ctx context.Context, ProtocolVersion: version.CurrentRPCProtocolVersion(), UserAgent: loop.UserAgent(f.loopIn.Initiator), PaymentTimeoutSeconds: f.loopIn.PaymentTimeoutSeconds, + Fast: f.loopIn.Fast, } if f.loopIn.LastHop != nil { loopInReq.LastHop = f.loopIn.LastHop diff --git a/staticaddr/loopin/interface.go b/staticaddr/loopin/interface.go index 7efdf7e3..c4582730 100644 --- a/staticaddr/loopin/interface.go +++ b/staticaddr/loopin/interface.go @@ -91,8 +91,8 @@ 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) (*loop.LoopInQuote, error) + routeHints [][]zpay32.HopHint, initiator string, + numDeposits uint32, fast bool) (*loop.LoopInQuote, error) } type NotificationManager interface { diff --git a/staticaddr/loopin/loopin.go b/staticaddr/loopin/loopin.go index 1e198f4f..cca73bab 100644 --- a/staticaddr/loopin/loopin.go +++ b/staticaddr/loopin/loopin.go @@ -101,6 +101,10 @@ type StaticAddressLoopIn struct { // used. SelectedAmount btcutil.Amount + // Fast indicates whether the client requested fast publication behavior + // on the server side for this static loop in. + Fast bool + // state is the current state of the swap. state fsm.StateType diff --git a/staticaddr/loopin/manager.go b/staticaddr/loopin/manager.go index 44c1343b..478b85f4 100644 --- a/staticaddr/loopin/manager.go +++ b/staticaddr/loopin/manager.go @@ -743,14 +743,14 @@ func (m *Manager) initiateLoopIn(ctx context.Context, numDeposits := uint32(len(selectedDeposits)) quote, err := m.cfg.QuoteGetter.GetLoopInQuote( ctx, swapAmount, m.cfg.NodePubkey, req.LastHop, req.RouteHints, - req.Initiator, numDeposits, + req.Initiator, numDeposits, req.Fast, ) if err != nil { return nil, fmt.Errorf("unable to get loop in quote: %w", err) } - // If the previously accepted quote fee is lower than what is quoted now - // we abort the swap. + // If the previously accepted quote fee is lower than what is quoted, we + // abort the swap. if quote.SwapFee > req.MaxSwapFee { log.Warnf("Swap fee %v exceeding maximum of %v", quote.SwapFee, req.MaxSwapFee) @@ -774,6 +774,7 @@ func (m *Manager) initiateLoopIn(ctx context.Context, QuotedSwapFee: quote.SwapFee, MaxSwapFee: req.MaxSwapFee, PaymentTimeoutSeconds: paymentTimeoutSeconds, + Fast: req.Fast, } if req.LastHop != nil { swap.LastHop = req.LastHop[:] diff --git a/staticaddr/loopin/sql_store.go b/staticaddr/loopin/sql_store.go index e291680d..da4c9298 100644 --- a/staticaddr/loopin/sql_store.go +++ b/staticaddr/loopin/sql_store.go @@ -278,6 +278,7 @@ func (s *SqlStore) CreateLoopIn(ctx context.Context, DepositOutpoints: joinedOutpoints, SelectedAmount: int64(loopIn.SelectedAmount), PaymentTimeoutSeconds: int32(loopIn.PaymentTimeoutSeconds), + Fast: loopIn.Fast, } updateArgs := sqlc.InsertStaticAddressMetaUpdateParams{ @@ -581,6 +582,7 @@ func toStaticAddressLoopIn(_ context.Context, network *chaincfg.Params, QuotedSwapFee: btcutil.Amount(swap.QuotedSwapFeeSatoshis), DepositOutpoints: depositOutpoints, SelectedAmount: btcutil.Amount(swap.SelectedAmount), + Fast: swap.Fast, HtlcTxFeeRate: chainfee.SatPerKWeight( swap.HtlcTxFeeRateSatKw, ),