Skip to content

Commit 76e8edf

Browse files
committed
staticaddr: fractional loop-in amount
1 parent 51bac8f commit 76e8edf

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ type StaticAddressLoopInRequest struct {
338338
// swap payment. If the timeout is reached the swap will be aborted and
339339
// the client can retry the swap if desired with different parameters.
340340
PaymentTimeoutSeconds uint32
341+
342+
SelectedAmount btcutil.Amount
341343
}
342344

343345
// LoopInTerms are the server terms on which it executes loop in swaps.

staticaddr/loopin/actions.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,14 @@ func (f *FSM) InitHtlcAction(ctx context.Context,
6868
}
6969

7070
// Calculate the swap invoice amount. The server needs to pay us the
71-
// sum of all deposits minus the fees that the server charges for the
72-
// swap.
73-
swapInvoiceAmt := f.loopIn.TotalDepositAmount() - f.loopIn.QuotedSwapFee
71+
// swap amount minus the fees that the server charges for the swap. The
72+
// swap amount is either the total value of the selected deposits, or
73+
// the selected amount if a specific amount was requested.
74+
swapAmount := f.loopIn.TotalDepositAmount()
75+
if f.loopIn.SelectedAmount > 0 {
76+
swapAmount = f.loopIn.SelectedAmount
77+
}
78+
swapInvoiceAmt := swapAmount - f.loopIn.QuotedSwapFee
7479

7580
// Generate random preimage.
7681
var swapPreimage lntypes.Preimage

staticaddr/loopin/loopin.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ type StaticAddressLoopIn struct {
9393
// swap.
9494
DepositOutpoints []string
9595

96+
SelectedAmount btcutil.Amount
97+
9698
// state is the current state of the swap.
9799
state fsm.StateType
98100

@@ -287,10 +289,18 @@ func (l *StaticAddressLoopIn) createHtlcTx(chainParams *chaincfg.Params,
287289
weight := l.htlcWeight()
288290
fee := feeRate.FeeForWeight(weight)
289291

290-
// Check if the server breaches our fee limits.
291-
amt := float64(l.TotalDepositAmount())
292-
feeLimit := btcutil.Amount(amt * maxFeePercentage)
292+
// Determine the swap amount. If the user selected a specific amount, we
293+
// use that and use the difference to the total deposit amount as the
294+
// change.
295+
swapAmt := float64(l.TotalDepositAmount())
296+
var changeAmount btcutil.Amount
297+
if l.SelectedAmount > 0 {
298+
swapAmt = float64(l.SelectedAmount)
299+
changeAmount = l.TotalDepositAmount() - l.SelectedAmount
300+
}
293301

302+
// Check if the server breaches our fee limits.
303+
feeLimit := btcutil.Amount(swapAmt * maxFeePercentage)
294304
if fee > feeLimit {
295305
return nil, fmt.Errorf("htlc tx fee %v exceeds max fee %v",
296306
fee, feeLimit)
@@ -314,6 +324,14 @@ func (l *StaticAddressLoopIn) createHtlcTx(chainParams *chaincfg.Params,
314324

315325
msgTx.AddTxOut(sweepOutput)
316326

327+
// We expect change to be sent back to our static address output script.
328+
if changeAmount > 0 {
329+
msgTx.AddTxOut(&wire.TxOut{
330+
Value: int64(changeAmount),
331+
PkScript: l.AddressParams.PkScript,
332+
})
333+
}
334+
317335
return msgTx, nil
318336
}
319337

staticaddr/loopin/manager.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"github.com/lightninglabs/loop/staticaddr/deposit"
2121
"github.com/lightninglabs/loop/swapserverrpc"
2222
looprpc "github.com/lightninglabs/loop/swapserverrpc"
23+
"github.com/lightningnetwork/lnd/input"
2324
"github.com/lightningnetwork/lnd/lntypes"
25+
"github.com/lightningnetwork/lnd/lnwallet"
2426
"github.com/lightningnetwork/lnd/routing/route"
2527
)
2628

@@ -205,8 +207,8 @@ func (m *Manager) Run(ctx context.Context, currentHeight uint32) error {
205207
case request.respChan <- resp:
206208

207209
case <-ctx.Done():
208-
// Noify subroutines that the main loop has been
209-
// canceled.
210+
// Notify subroutines that the main loop has
211+
// been canceled.
210212
close(m.exitChan)
211213

212214
return ctx.Err()
@@ -549,6 +551,15 @@ func (m *Manager) initiateLoopIn(ctx context.Context,
549551
}
550552
totalDepositAmount := tmp.TotalDepositAmount()
551553

554+
// If the selected amount would leave a dust change output or exceeds
555+
// the total deposits value, we return an error.
556+
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize)
557+
if totalDepositAmount-req.SelectedAmount < dustLimit {
558+
return nil, fmt.Errorf("selected amount %v leaves "+
559+
"dust or exceeds total deposit value %v",
560+
req.SelectedAmount, totalDepositAmount)
561+
}
562+
552563
// Check that the label is valid.
553564
err := labels.Validate(req.Label)
554565
if err != nil {
@@ -616,6 +627,7 @@ func (m *Manager) initiateLoopIn(ctx context.Context,
616627
}
617628

618629
swap := &StaticAddressLoopIn{
630+
SelectedAmount: req.SelectedAmount,
619631
DepositOutpoints: req.DepositOutpoints,
620632
Deposits: deposits,
621633
Label: req.Label,

0 commit comments

Comments
 (0)