Skip to content

Commit bef9c15

Browse files
committed
all coinselect changes
1 parent be99229 commit bef9c15

File tree

7 files changed

+1055
-957
lines changed

7 files changed

+1055
-957
lines changed

cmd/loop/staticaddr.go

Lines changed: 16 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/hex"
66
"errors"
77
"fmt"
8-
"sort"
98
"strconv"
109
"strings"
1110

@@ -15,8 +14,6 @@ import (
1514
"github.com/lightninglabs/loop/staticaddr/deposit"
1615
"github.com/lightninglabs/loop/staticaddr/loopin"
1716
"github.com/lightninglabs/loop/swapserverrpc"
18-
"github.com/lightningnetwork/lnd/input"
19-
"github.com/lightningnetwork/lnd/lnwallet"
2017
"github.com/lightningnetwork/lnd/routing/route"
2118
"github.com/urfave/cli"
2219
)
@@ -509,17 +506,16 @@ func staticAddressLoopIn(ctx *cli.Context) error {
509506
defer cleanup()
510507

511508
var (
512-
ctxb = context.Background()
513-
isAllSelected = ctx.IsSet("all")
514-
isUtxoSelected = ctx.IsSet("utxo")
515-
isAmountSelected bool
516-
selectedAmount = ctx.Int64("amount")
517-
label = ctx.String("static-loop-in")
518-
hints []*swapserverrpc.RouteHint
519-
lastHop []byte
520-
paymentTimeoutSeconds = uint32(loopin.DefaultPaymentTimeoutSeconds)
509+
ctxb = context.Background()
510+
isAllSelected = ctx.IsSet("all")
511+
isUtxoSelected = ctx.IsSet("utxo")
512+
selectedAmount = ctx.Int64("amount")
513+
selectDepositsForQuote bool
514+
label = ctx.String("static-loop-in")
515+
hints []*swapserverrpc.RouteHint
516+
lastHop []byte
517+
paymentTimeoutSeconds = uint32(loopin.DefaultPaymentTimeoutSeconds)
521518
)
522-
isAmountSelected = selectedAmount > 0
523519

524520
// Validate our label early so that we can fail before getting a quote.
525521
if err := labels.Validate(label); err != nil {
@@ -575,15 +571,8 @@ func staticAddressLoopIn(ctx *cli.Context) error {
575571
case isUtxoSelected:
576572
depositOutpoints = ctx.StringSlice("utxo")
577573

578-
case isAmountSelected:
579-
// If there's only a swap amount specified we'll coin-select
580-
// deposits to cover the swap amount.
581-
depositOutpoints, err = selectDeposits(
582-
allDeposits, selectedAmount,
583-
)
584-
if err != nil {
585-
return err
586-
}
574+
case selectedAmount > 0:
575+
// If only an amount is selected we will trigger coin selection.
587576

588577
default:
589578
return fmt.Errorf("unknown quote request")
@@ -593,12 +582,17 @@ func staticAddressLoopIn(ctx *cli.Context) error {
593582
return errors.New("duplicate outpoints detected")
594583
}
595584

585+
if len(depositOutpoints) == 0 && selectedAmount > 0 {
586+
selectDepositsForQuote = true
587+
}
588+
596589
quoteReq := &looprpc.QuoteRequest{
597590
Amt: selectedAmount,
598591
LoopInRouteHints: hints,
599592
LoopInLastHop: lastHop,
600593
Private: ctx.Bool(privateFlag.Name),
601594
DepositOutpoints: depositOutpoints,
595+
SelectDeposits: selectDepositsForQuote,
602596
}
603597
quote, err := client.GetLoopInQuote(ctxb, quoteReq)
604598
if err != nil {
@@ -640,47 +634,6 @@ func staticAddressLoopIn(ctx *cli.Context) error {
640634
return nil
641635
}
642636

643-
// selectDeposits sorts the deposits by amount in descending order, then by
644-
// blocks-until-expiry in ascending order. It then selects the deposits that
645-
// are needed to cover the amount requested without leaving a dust change. It
646-
// returns an error if the sum of deposits minus dust is less than the requested
647-
// amount.
648-
func selectDeposits(deposits []*looprpc.Deposit, targetAmount int64) ([]string,
649-
error) {
650-
651-
// Sort the deposits by amount in descending order, then by
652-
// blocks-until-expiry in ascending order.
653-
sort.Slice(deposits, func(i, j int) bool {
654-
if deposits[i].Value == deposits[j].Value {
655-
return deposits[i].BlocksUntilExpiry <
656-
deposits[j].BlocksUntilExpiry
657-
}
658-
return deposits[i].Value > deposits[j].Value
659-
})
660-
661-
// Select the deposits that are needed to cover the swap amount without
662-
// leaving a dust change.
663-
var selectedDeposits []string
664-
var selectedAmount int64
665-
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize)
666-
for _, deposit := range deposits {
667-
selectedDeposits = append(selectedDeposits, deposit.Outpoint)
668-
selectedAmount += deposit.Value
669-
if selectedAmount == targetAmount {
670-
return selectedDeposits, nil
671-
}
672-
if selectedAmount > targetAmount {
673-
if selectedAmount-targetAmount >= int64(dustLimit) {
674-
return selectedDeposits, nil
675-
}
676-
}
677-
}
678-
679-
return nil, fmt.Errorf("not enough deposits to cover "+
680-
"requested amount, selected %d but need %d",
681-
selectedAmount, targetAmount)
682-
}
683-
684637
func containsDuplicates(outpoints []string) bool {
685638
found := make(map[string]struct{})
686639
for _, outpoint := range outpoints {

loopd/swapclient_server.go

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -895,25 +895,54 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
895895
var (
896896
selectedAmount = btcutil.Amount(req.Amt)
897897
totalDepositAmount btcutil.Amount
898-
numDeposits = len(req.DepositOutpoints)
898+
autoSelectDeposits = req.SelectDeposits
899899
err error
900900
)
901901

902902
htlcConfTarget, err := validateLoopInRequest(
903-
req.ConfTarget, req.ExternalHtlc, uint32(numDeposits),
904-
int64(selectedAmount),
903+
req.ConfTarget, req.ExternalHtlc,
904+
uint32(len(req.DepositOutpoints)), int64(selectedAmount),
905+
autoSelectDeposits,
905906
)
906907
if err != nil {
907908
return nil, err
908909
}
909910

910-
// Retrieve deposits to calculate their total value.
911-
var depositList *looprpc.ListStaticAddressDepositsResponse
911+
// If deposits should be automatically selected we do so and count the
912+
// number of deposits to quote for.
913+
numDeposits := 0
914+
if autoSelectDeposits {
915+
deposits, err := s.depositManager.GetActiveDepositsInState(
916+
deposit.Deposited,
917+
)
918+
if err != nil {
919+
return nil, fmt.Errorf("unable to retrieve all "+
920+
"deposits: %w", err)
921+
}
922+
923+
// TODO(hieblmi): add params to deposit for multi-address
924+
// support.
925+
params, err := s.staticAddressManager.GetStaticAddressParameters(
926+
ctx,
927+
)
928+
if err != nil {
929+
return nil, fmt.Errorf("unable to retrieve static "+
930+
"address parameters: %w", err)
931+
}
912932

913-
// If deposits are selected, we need to retrieve them to calculate the
914-
// total value which we request a quote for.
915-
if numDeposits > 0 {
916-
depositList, err = s.ListStaticAddressDeposits(
933+
selectedDeposits, err := s.staticLoopInManager.SelectDeposits(
934+
selectedAmount, deposits, params.Expiry,
935+
)
936+
if err != nil {
937+
return nil, fmt.Errorf("unable to select deposits: %w",
938+
err)
939+
}
940+
941+
numDeposits = len(selectedDeposits)
942+
} else if len(req.DepositOutpoints) > 0 {
943+
// If deposits are selected, we need to retrieve them to
944+
// calculate the total value which we request a quote for.
945+
depositList, err := s.ListStaticAddressDeposits(
917946
ctx, &looprpc.ListStaticAddressDepositsRequest{
918947
Outpoints: req.DepositOutpoints,
919948
},
@@ -927,9 +956,13 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
927956
"deposit outpoints")
928957
}
929958

930-
if numDeposits != len(depositList.FilteredDeposits) {
959+
if len(req.DepositOutpoints) !=
960+
len(depositList.FilteredDeposits) {
961+
931962
return nil, fmt.Errorf("expected %d deposits, got %d",
932963
numDeposits, len(depositList.FilteredDeposits))
964+
} else {
965+
numDeposits = len(depositList.FilteredDeposits)
933966
}
934967

935968
// In case we quote for deposits we send the server both the
@@ -942,12 +975,15 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
942975
)
943976
}
944977

945-
selectedAmount, err = s.staticLoopInManager.SwapAmountFromSelectedAmount(
946-
selectedAmount, totalDepositAmount,
978+
// If a fractional amount is also selected, we check if it would
979+
// lead to a dust change output.
980+
selectedAmount, err = loopin.SwapAmountFromSelectedAmount(
981+
totalDepositAmount, selectedAmount,
947982
)
948983
if err != nil {
949-
return nil, fmt.Errorf("error calculating swap "+
950-
"amount from selected amount: %v", err)
984+
return nil, fmt.Errorf("error calculating "+
985+
"swap amount from selected amount: %v",
986+
err)
951987
}
952988
}
953989

@@ -1077,8 +1113,11 @@ func (s *swapClientServer) LoopIn(ctx context.Context,
10771113

10781114
infof("Loop in request received")
10791115

1116+
selectDeposits := false
1117+
numDeposits := uint32(0)
10801118
htlcConfTarget, err := validateLoopInRequest(
1081-
in.HtlcConfTarget, in.ExternalHtlc, 0, in.Amt,
1119+
in.HtlcConfTarget, in.ExternalHtlc, numDeposits, in.Amt,
1120+
selectDeposits,
10821121
)
10831122
if err != nil {
10841123
return nil, err
@@ -2184,10 +2223,17 @@ func validateConfTarget(target, defaultTarget int32) (int32, error) {
21842223
// validateLoopInRequest fails if the mutually exclusive conf target and
21852224
// external parameters are both set.
21862225
func validateLoopInRequest(htlcConfTarget int32, external bool,
2187-
numDeposits uint32, amount int64) (int32, error) {
2226+
numDeposits uint32, amount int64, autoSelectDeposits bool) (int32,
2227+
error) {
21882228

21892229
if amount == 0 && numDeposits == 0 {
2190-
return 0, errors.New("either amount or deposits must be set")
2230+
return 0, errors.New("either amount, or deposits or both " +
2231+
"must be set")
2232+
}
2233+
2234+
if autoSelectDeposits && numDeposits > 0 {
2235+
return 0, errors.New("cannot auto-select deposits while " +
2236+
"providing deposits at the same time")
21912237
}
21922238

21932239
// If the htlc is going to be externally set, the htlcConfTarget should
@@ -2205,7 +2251,7 @@ func validateLoopInRequest(htlcConfTarget int32, external bool,
22052251

22062252
// If the loop in uses static address deposits, we do not need to set a
22072253
// confirmation target since the HTLC won't be published by the client.
2208-
if numDeposits > 0 {
2254+
if numDeposits > 0 || autoSelectDeposits {
22092255
return 0, nil
22102256
}
22112257

0 commit comments

Comments
 (0)