Skip to content

Commit f64fbd7

Browse files
committed
all coinselect changes
1 parent 7866842 commit f64fbd7

File tree

7 files changed

+1057
-958
lines changed

7 files changed

+1057
-958
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: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -895,27 +895,57 @@ 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{
918-
Outpoints: req.DepositOutpoints,
947+
StateFilter: looprpc.DepositState_DEPOSITED,
948+
Outpoints: req.DepositOutpoints,
919949
},
920950
)
921951
if err != nil {
@@ -927,9 +957,13 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
927957
"deposit outpoints")
928958
}
929959

930-
if numDeposits != len(depositList.FilteredDeposits) {
960+
if len(req.DepositOutpoints) !=
961+
len(depositList.FilteredDeposits) {
962+
931963
return nil, fmt.Errorf("expected %d deposits, got %d",
932964
numDeposits, len(depositList.FilteredDeposits))
965+
} else {
966+
numDeposits = len(depositList.FilteredDeposits)
933967
}
934968

935969
// In case we quote for deposits we send the server both the
@@ -942,12 +976,15 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
942976
)
943977
}
944978

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

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

10781115
infof("Loop in request received")
10791116

1117+
selectDeposits := false
1118+
numDeposits := uint32(0)
10801119
htlcConfTarget, err := validateLoopInRequest(
1081-
in.HtlcConfTarget, in.ExternalHtlc, 0, in.Amt,
1120+
in.HtlcConfTarget, in.ExternalHtlc, numDeposits, in.Amt,
1121+
selectDeposits,
10821122
)
10831123
if err != nil {
10841124
return nil, err
@@ -2184,10 +2224,17 @@ func validateConfTarget(target, defaultTarget int32) (int32, error) {
21842224
// validateLoopInRequest fails if the mutually exclusive conf target and
21852225
// external parameters are both set.
21862226
func validateLoopInRequest(htlcConfTarget int32, external bool,
2187-
numDeposits uint32, amount int64) (int32, error) {
2227+
numDeposits uint32, amount int64, autoSelectDeposits bool) (int32,
2228+
error) {
21882229

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

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

22062253
// If the loop in uses static address deposits, we do not need to set a
22072254
// confirmation target since the HTLC won't be published by the client.
2208-
if numDeposits > 0 {
2255+
if numDeposits > 0 || autoSelectDeposits {
22092256
return 0, nil
22102257
}
22112258

0 commit comments

Comments
 (0)