Skip to content

Commit 1fe0fb1

Browse files
committed
all withdrawal amount changes
1 parent 5b68e42 commit 1fe0fb1

File tree

7 files changed

+640
-562
lines changed

7 files changed

+640
-562
lines changed

cmd/loop/staticaddr.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ var withdrawalCommand = cli.Command{
143143
Usage: "withdraws all static address deposits.",
144144
},
145145
cli.StringFlag{
146-
Name: "addr",
146+
Name: "dest_addr",
147147
Usage: "the optional address that the withdrawn " +
148148
"funds should be sent to, if let blank the " +
149149
"funds will go to lnd's wallet",
@@ -154,6 +154,12 @@ var withdrawalCommand = cli.Command{
154154
"sat/vbyte that should be used when crafting " +
155155
"the transaction",
156156
},
157+
cli.IntFlag{
158+
Name: "amount",
159+
Usage: "the number of satoshis that should be " +
160+
"withdrawn from the selected deposits. The " +
161+
"change is sent back to the static address",
162+
},
157163
},
158164
Action: withdraw,
159165
}
@@ -193,8 +199,13 @@ func withdraw(ctx *cli.Context) error {
193199
return fmt.Errorf("unknown withdrawal request")
194200
}
195201

196-
if ctx.IsSet("addr") {
197-
destAddr = ctx.String("addr")
202+
if ctx.IsSet("dest_addr") {
203+
destAddr = ctx.String("dest_addr")
204+
}
205+
206+
if ctx.IsSet("change_addr") && !ctx.IsSet("amount") {
207+
return errors.New("change address can only be set if an " +
208+
"amount is selected")
198209
}
199210

200211
resp, err := client.WithdrawDeposits(ctxb,
@@ -203,6 +214,7 @@ func withdraw(ctx *cli.Context) error {
203214
All: isAllSelected,
204215
DestAddr: destAddr,
205216
SatPerVbyte: int64(ctx.Uint64("sat_per_vbyte")),
217+
Amount: ctx.Int64("amount"),
206218
})
207219
if err != nil {
208220
return err

loopd/swapclient_server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ func (s *swapClientServer) WithdrawDeposits(ctx context.Context,
14471447
}
14481448

14491449
txhash, pkScript, err := s.withdrawalManager.DeliverWithdrawalRequest(
1450-
ctx, outpoints, req.DestAddr, req.SatPerVbyte,
1450+
ctx, outpoints, req.DestAddr, req.SatPerVbyte, req.Amount,
14511451
)
14521452
if err != nil {
14531453
return nil, err

looprpc/client.pb.go

Lines changed: 409 additions & 393 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

looprpc/client.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,16 @@ message WithdrawDepositsRequest {
15921592
The fee rate in sat/vbyte to use for the withdrawal transaction.
15931593
*/
15941594
int64 sat_per_vbyte = 4;
1595+
1596+
/*
1597+
The amount in satoshis that should be withdrawn from the selected deposits.
1598+
If there is change, it will be sent to the change address, if specified, and
1599+
to an internal wallet address otherwise. The fees for the transaction are
1600+
taken out from the change output, and if not fully covered, the rest will be
1601+
taken from the withdrawn amount. If the change is below the dust amount, it
1602+
will be added to the miner fee.
1603+
*/
1604+
int64 amount = 5;
15951605
}
15961606

15971607
message WithdrawDepositsResponse {

staticaddr/withdraw/manager.go

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type newWithdrawalRequest struct {
7575
respChan chan *newWithdrawalResponse
7676
destAddr string
7777
satPerVbyte int64
78+
amount int64
7879
}
7980

8081
// newWithdrawalResponse is used to return withdrawal info and error to the
@@ -156,10 +157,10 @@ func (m *Manager) Run(ctx context.Context, currentHeight uint32) error {
156157
err)
157158
}
158159

159-
case request := <-m.newWithdrawalRequestChan:
160+
case req := <-m.newWithdrawalRequestChan:
160161
txHash, pkScript, err = m.WithdrawDeposits(
161-
ctx, request.outpoints, request.destAddr,
162-
request.satPerVbyte,
162+
ctx, req.outpoints, req.destAddr,
163+
req.satPerVbyte, req.amount,
163164
)
164165
if err != nil {
165166
log.Errorf("Error withdrawing deposits: %v",
@@ -174,7 +175,7 @@ func (m *Manager) Run(ctx context.Context, currentHeight uint32) error {
174175
err: err,
175176
}
176177
select {
177-
case request.respChan <- resp:
178+
case req.respChan <- resp:
178179

179180
case <-ctx.Done():
180181
// Notify subroutines that the main loop has
@@ -261,8 +262,8 @@ func (m *Manager) WaitInitComplete() {
261262

262263
// WithdrawDeposits starts a deposits withdrawal flow.
263264
func (m *Manager) WithdrawDeposits(ctx context.Context,
264-
outpoints []wire.OutPoint, destAddr string, satPerVbyte int64) (string,
265-
string, error) {
265+
outpoints []wire.OutPoint, destAddr string, satPerVbyte int64,
266+
amount int64) (string, string, error) {
266267

267268
if len(outpoints) == 0 {
268269
return "", "", fmt.Errorf("no outpoints selected to " +
@@ -272,7 +273,8 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
272273
// Ensure that the deposits are in a state in which they can be
273274
// withdrawn.
274275
deposits, allActive := m.cfg.DepositManager.AllOutpointsActiveDeposits(
275-
outpoints, deposit.Deposited)
276+
outpoints, deposit.Deposited,
277+
)
276278

277279
if !allActive {
278280
return "", "", ErrWithdrawingInactiveDeposits
@@ -302,8 +304,27 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
302304
}
303305
}
304306

307+
if amount > 0 {
308+
// Check that the amount is within the range of the deposits.
309+
totalValue := withdrawalValue(m.toPrevOuts(deposits, nil))
310+
if amount > int64(totalValue) {
311+
return "", "", fmt.Errorf("amount to withdraw is " +
312+
"greater than the total value of the " +
313+
"deposits selected")
314+
}
315+
316+
// We'll hint the user if the remaining amount is below the dust
317+
// limit and hence will go towards miner fees.
318+
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize)
319+
if totalValue-btcutil.Amount(amount) < dustLimit {
320+
log.Warnf("The remaining amount after withdrawal is "+
321+
"below the dust limit of %v and will go "+
322+
"towards miner fees", dustLimit)
323+
}
324+
}
325+
305326
finalizedTx, err := m.createFinalizedWithdrawalTx(
306-
ctx, deposits, withdrawalAddress, satPerVbyte,
327+
ctx, deposits, withdrawalAddress, satPerVbyte, amount,
307328
)
308329
if err != nil {
309330
return "", "", err
@@ -355,7 +376,7 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
355376

356377
func (m *Manager) createFinalizedWithdrawalTx(ctx context.Context,
357378
deposits []*deposit.Deposit, withdrawalAddress btcutil.Address,
358-
satPerVbyte int64) (*wire.MsgTx, error) {
379+
satPerVbyte int64, amount int64) (*wire.MsgTx, error) {
359380

360381
// Create a musig2 session for each deposit.
361382
withdrawalSessions, clientNonces, err := m.createMusig2Sessions(
@@ -387,6 +408,7 @@ func (m *Manager) createFinalizedWithdrawalTx(ctx context.Context,
387408
ClientNonces: clientNonces,
388409
ClientSweepAddr: withdrawalAddress.String(),
389410
TxFeeRate: uint64(withdrawalSweepFeeRate),
411+
Amount: amount,
390412
},
391413
)
392414
if err != nil {
@@ -814,13 +836,14 @@ func (m *Manager) republishWithdrawals(ctx context.Context) error {
814836
// DeliverWithdrawalRequest forwards a withdrawal request to the manager main
815837
// loop.
816838
func (m *Manager) DeliverWithdrawalRequest(ctx context.Context,
817-
outpoints []wire.OutPoint, destAddr string, satPerVbyte int64) (string,
818-
string, error) {
839+
outpoints []wire.OutPoint, destAddr string, satPerVbyte int64,
840+
amount int64) (string, string, error) {
819841

820842
request := newWithdrawalRequest{
821843
outpoints: outpoints,
822844
destAddr: destAddr,
823845
satPerVbyte: satPerVbyte,
846+
amount: amount,
824847
respChan: make(chan *newWithdrawalResponse),
825848
}
826849

0 commit comments

Comments
 (0)