6
6
"fmt"
7
7
"sort"
8
8
9
+ "github.com/btcsuite/btcd/btcutil"
9
10
"github.com/btcsuite/btcd/chaincfg/chainhash"
10
11
"github.com/btcsuite/btcd/wire"
11
12
"github.com/lightninglabs/lndclient"
@@ -14,6 +15,7 @@ import (
14
15
"github.com/lightninglabs/loop/staticaddr/script"
15
16
"github.com/lightninglabs/loop/swapserverrpc"
16
17
"github.com/lightningnetwork/lnd/input"
18
+ "github.com/lightningnetwork/lnd/lnwallet"
17
19
)
18
20
19
21
func ToPrevOuts (deposits []* deposit.Deposit ,
@@ -65,6 +67,36 @@ func CreateMusig2Sessions(ctx context.Context,
65
67
return musig2Sessions , clientNonces , nil
66
68
}
67
69
70
+ // CreateMusig2SessionsPerDeposit creates a musig2 session for a number of
71
+ // deposits.
72
+ func CreateMusig2SessionsPerDeposit (ctx context.Context ,
73
+ signer lndclient.SignerClient , deposits []* deposit.Deposit ,
74
+ addrParams * address.Parameters ,
75
+ staticAddress * script.StaticAddress ) (
76
+ map [string ]* input.MuSig2SessionInfo , map [string ][]byte , map [string ]int ,
77
+ error ) {
78
+
79
+ sessions := make (map [string ]* input.MuSig2SessionInfo )
80
+ nonces := make (map [string ][]byte )
81
+ depositToIdx := make (map [string ]int )
82
+
83
+ // Create the musig2 sessions for the sweepless sweep tx.
84
+ for i , deposit := range deposits {
85
+ session , err := createMusig2Session (
86
+ ctx , signer , addrParams , staticAddress ,
87
+ )
88
+ if err != nil {
89
+ return nil , nil , nil , err
90
+ }
91
+
92
+ sessions [deposit .String ()] = session
93
+ nonces [deposit .String ()] = session .PublicNonce [:]
94
+ depositToIdx [deposit .String ()] = i
95
+ }
96
+
97
+ return sessions , nonces , depositToIdx , nil
98
+ }
99
+
68
100
// createMusig2Session creates a musig2 session for the deposit.
69
101
func createMusig2Session (ctx context.Context ,
70
102
signer lndclient.SignerClient , addrParams * address.Parameters ,
@@ -131,3 +163,42 @@ func bip69inputLess(input1, input2 *swapserverrpc.PrevoutInfo) bool {
131
163
}
132
164
return bytes .Compare (ihash [:], jhash [:]) == - 1
133
165
}
166
+
167
+ // SelectDeposits sorts the deposits by amount in descending order. It then
168
+ // selects the deposits that are needed to cover the amount requested without
169
+ // leaving a dust change. It returns an error if the sum of deposits minus dust
170
+ // is less than the requested amount.
171
+ func SelectDeposits (deposits []* deposit.Deposit , amount int64 ) (
172
+ []* deposit.Deposit , error ) {
173
+
174
+ // Check that sum of deposits covers the swap amount while leaving no
175
+ // dust change.
176
+ dustLimit := lnwallet .DustLimitForSize (input .P2TRSize )
177
+ var depositSum btcutil.Amount
178
+ for _ , deposit := range deposits {
179
+ depositSum += deposit .Value
180
+ }
181
+ if depositSum - dustLimit < btcutil .Amount (amount ) {
182
+ return nil , fmt .Errorf ("insufficient funds to cover swap " +
183
+ "amount, try manually selecting deposits" )
184
+ }
185
+
186
+ // Sort the deposits by amount in descending order.
187
+ sort .Slice (deposits , func (i , j int ) bool {
188
+ return deposits [i ].Value > deposits [j ].Value
189
+ })
190
+
191
+ // Select the deposits that are needed to cover the swap amount without
192
+ // leaving a dust change.
193
+ var selectedDeposits []* deposit.Deposit
194
+ var selectedAmount btcutil.Amount
195
+ for _ , deposit := range deposits {
196
+ if selectedAmount >= btcutil .Amount (amount )+ dustLimit {
197
+ break
198
+ }
199
+ selectedDeposits = append (selectedDeposits , deposit )
200
+ selectedAmount += deposit .Value
201
+ }
202
+
203
+ return selectedDeposits , nil
204
+ }
0 commit comments