Skip to content

Commit acea303

Browse files
committed
staticaddr: check dust limits before withdrawing
1 parent 10b970c commit acea303

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

staticaddr/withdraw/manager.go

+37-24
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,39 @@ func (m *Manager) createFinalizedWithdrawalTx(ctx context.Context,
380380
).FeePerKWeight()
381381
}
382382

383+
// We'll now check the selected fee rate leaves a withdrawal output that
384+
// is above the dust limit. If not we cancel the withdrawal instead of
385+
// requesting a signature from the server.
386+
addressParams, err := m.cfg.AddressManager.GetStaticAddressParameters(
387+
ctx,
388+
)
389+
if err != nil {
390+
return nil, fmt.Errorf("couldn't get confirmation height for "+
391+
"deposit, %w", err)
392+
}
393+
394+
// Calculate the fee value in satoshis.
383395
outpoints := toOutpoints(deposits)
396+
weight, err := withdrawalFee(len(outpoints), withdrawalAddress)
397+
if err != nil {
398+
return nil, err
399+
}
400+
feeValue := withdrawalSweepFeeRate.FeeForWeight(weight)
401+
402+
var (
403+
prevOuts = m.toPrevOuts(deposits, addressParams.PkScript)
404+
totalValue = withdrawalValue(prevOuts)
405+
outputValue = int64(totalValue) - int64(feeValue)
406+
// P2TRSize calculates a dust limit based on a 40 byte maximum
407+
// size witness output.
408+
dustLimit = lnwallet.DustLimitForSize(input.P2TRSize)
409+
)
410+
411+
if outputValue < int64(dustLimit) {
412+
return nil, fmt.Errorf("withdrawal output value %d sats "+
413+
"below dust limit %d sats", outputValue, dustLimit)
414+
}
415+
384416
resp, err := m.cfg.StaticAddressServerClient.ServerWithdrawDeposits(
385417
ctx, &staticaddressrpc.ServerWithdrawRequest{
386418
Outpoints: toPrevoutInfo(outpoints),
@@ -393,19 +425,9 @@ func (m *Manager) createFinalizedWithdrawalTx(ctx context.Context,
393425
return nil, err
394426
}
395427

396-
addressParams, err := m.cfg.AddressManager.GetStaticAddressParameters(
397-
ctx,
398-
)
399-
if err != nil {
400-
return nil, fmt.Errorf("couldn't get confirmation height for "+
401-
"deposit, %w", err)
402-
}
403-
404-
prevOuts := m.toPrevOuts(deposits, addressParams.PkScript)
405-
totalValue := withdrawalValue(prevOuts)
428+
withdrawalOutputValue := int64(totalValue - feeValue)
406429
withdrawalTx, err := m.createWithdrawalTx(
407-
outpoints, totalValue, withdrawalAddress,
408-
withdrawalSweepFeeRate,
430+
outpoints, withdrawalOutputValue, withdrawalAddress,
409431
)
410432
if err != nil {
411433
return nil, err
@@ -613,9 +635,8 @@ func byteSliceTo66ByteSlice(b []byte) ([musig2.PubNonceSize]byte, error) {
613635
}
614636

615637
func (m *Manager) createWithdrawalTx(outpoints []wire.OutPoint,
616-
withdrawlAmount btcutil.Amount, clientSweepAddress btcutil.Address,
617-
feeRate chainfee.SatPerKWeight) (*wire.MsgTx,
618-
error) {
638+
withdrawlOutputValue int64, clientSweepAddress btcutil.Address) (
639+
*wire.MsgTx, error) {
619640

620641
// First Create the tx.
621642
msgTx := wire.NewMsgTx(2)
@@ -628,22 +649,14 @@ func (m *Manager) createWithdrawalTx(outpoints []wire.OutPoint,
628649
})
629650
}
630651

631-
// Estimate the fee.
632-
weight, err := withdrawalFee(len(outpoints), clientSweepAddress)
633-
if err != nil {
634-
return nil, err
635-
}
636-
637652
pkscript, err := txscript.PayToAddrScript(clientSweepAddress)
638653
if err != nil {
639654
return nil, err
640655
}
641656

642-
fee := feeRate.FeeForWeight(weight)
643-
644657
// Create the sweep output
645658
sweepOutput := &wire.TxOut{
646-
Value: int64(withdrawlAmount) - int64(fee),
659+
Value: withdrawlOutputValue,
647660
PkScript: pkscript,
648661
}
649662

0 commit comments

Comments
 (0)