Skip to content

Commit a72dae3

Browse files
committed
lnwallet: use new maxFeeRatio for sanityCheckFee func
1 parent 8517581 commit a72dae3

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

lnrpc/walletrpc/walletkit_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,7 +1921,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32,
19211921

19221922
changeAmt, needMore, err := chanfunding.CalculateChangeAmount(
19231923
inputSum, outputSum, packetFeeNoChange,
1924-
packetFeeWithChange, changeDustLimit, changeType,
1924+
packetFeeWithChange, changeDustLimit, changeType, 0,
19251925
)
19261926
if err != nil {
19271927
return nil, fmt.Errorf("error calculating change "+
@@ -1978,7 +1978,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32,
19781978

19791979
selectedCoins, changeAmount, err := chanfunding.CoinSelect(
19801980
feeRate, fundingAmount, changeDustLimit, coins,
1981-
strategy, estimator, changeType,
1981+
strategy, estimator, changeType, 0,
19821982
)
19831983
if err != nil {
19841984
return fmt.Errorf("error selecting coins: %w", err)

lnwallet/chanfunding/coin_select.go

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ const (
5858
// must assert that the output value of the selected existing output
5959
// already is above dust when using this change address type.
6060
ExistingChangeAddress ChangeAddressType = 2
61+
62+
// DefaultMaxFeeRatio is the default fee to total amount of outputs
63+
// ratio that is used to sanity check the fees of a transaction.
64+
DefaultMaxFeeRatio float64 = 0.2
6165
)
6266

6367
// selectInputs selects a slice of inputs necessary to meet the specified
@@ -143,16 +147,25 @@ func calculateFees(utxos []wallet.Coin, feeRate chainfee.SatPerKWeight,
143147
return requiredFeeNoChange, requiredFeeWithChange, nil
144148
}
145149

146-
// sanityCheckFee checks if the specified fee amounts to over 20% of the total
147-
// output amount and raises an error.
148-
func sanityCheckFee(totalOut, fee btcutil.Amount) error {
149-
// Fail if more than 20% goes to fees.
150-
// TODO(halseth): smarter fee limit. Make configurable or dynamic wrt
151-
// total funding size?
152-
if fee > totalOut/5 {
153-
return fmt.Errorf("fee (%v) exceeds 20%% of total output (%v)",
154-
fee, totalOut)
150+
// sanityCheckFee checks if the specified fee amounts to what the provided ratio
151+
// allows.
152+
func sanityCheckFee(totalOut, fee btcutil.Amount, maxFeeRatio float64) error {
153+
// Sanity check the maxFeeRatio itself.
154+
if maxFeeRatio <= 0.00 || maxFeeRatio > 1.00 {
155+
return fmt.Errorf("maxFeeRatio must be between 0.00 and 1.00 "+
156+
"got %.2f", maxFeeRatio)
157+
}
158+
159+
maxFee := btcutil.Amount(float64(totalOut) * maxFeeRatio)
160+
161+
// Check that the fees do not exceed the max allowed value.
162+
if fee > maxFee {
163+
return fmt.Errorf("fee %v exceeds max fee (%v) on total "+
164+
"output value %v with max fee ratio of %.2f", fee,
165+
maxFee, totalOut, maxFeeRatio)
155166
}
167+
168+
// All checks passed, we return nil to signal that the fees are valid.
156169
return nil
157170
}
158171

@@ -163,7 +176,8 @@ func sanityCheckFee(totalOut, fee btcutil.Amount) error {
163176
func CoinSelect(feeRate chainfee.SatPerKWeight, amt, dustLimit btcutil.Amount,
164177
coins []wallet.Coin, strategy wallet.CoinSelectionStrategy,
165178
existingWeight input.TxWeightEstimator,
166-
changeType ChangeAddressType) ([]wallet.Coin, btcutil.Amount, error) {
179+
changeType ChangeAddressType, maxFeeRatio float64) ([]wallet.Coin,
180+
btcutil.Amount, error) {
167181

168182
amtNeeded := amt
169183
for {
@@ -188,6 +202,7 @@ func CoinSelect(feeRate chainfee.SatPerKWeight, amt, dustLimit btcutil.Amount,
188202
changeAmount, newAmtNeeded, err := CalculateChangeAmount(
189203
totalSat, amt, requiredFeeNoChange,
190204
requiredFeeWithChange, dustLimit, changeType,
205+
maxFeeRatio,
191206
)
192207
if err != nil {
193208
return nil, 0, err
@@ -216,7 +231,8 @@ func CoinSelect(feeRate chainfee.SatPerKWeight, amt, dustLimit btcutil.Amount,
216231
// fees and that more coins need to be selected.
217232
func CalculateChangeAmount(totalInputAmt, requiredAmt, requiredFeeNoChange,
218233
requiredFeeWithChange, dustLimit btcutil.Amount,
219-
changeType ChangeAddressType) (btcutil.Amount, btcutil.Amount, error) {
234+
changeType ChangeAddressType, maxFeeRatio float64) (btcutil.Amount,
235+
btcutil.Amount, error) {
220236

221237
// This is just a sanity check to make sure the function is used
222238
// correctly.
@@ -266,7 +282,8 @@ func CalculateChangeAmount(totalInputAmt, requiredAmt, requiredFeeNoChange,
266282
// Sanity check the resulting output values to make sure we
267283
// don't burn a great part to fees.
268284
totalOut := requiredAmt + changeAmt
269-
err := sanityCheckFee(totalOut, totalInputAmt-totalOut)
285+
286+
err := sanityCheckFee(totalOut, totalInputAmt-totalOut, maxFeeRatio)
270287
if err != nil {
271288
return 0, 0, err
272289
}
@@ -280,9 +297,9 @@ func CalculateChangeAmount(totalInputAmt, requiredAmt, requiredFeeNoChange,
280297
func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
281298
dustLimit btcutil.Amount, coins []wallet.Coin,
282299
strategy wallet.CoinSelectionStrategy,
283-
existingWeight input.TxWeightEstimator,
284-
changeType ChangeAddressType) ([]wallet.Coin, btcutil.Amount,
285-
btcutil.Amount, error) {
300+
existingWeight input.TxWeightEstimator, changeType ChangeAddressType,
301+
maxFeeRatio float64) ([]wallet.Coin, btcutil.Amount, btcutil.Amount,
302+
error) {
286303

287304
// First perform an initial round of coin selection to estimate
288305
// the required fee.
@@ -331,7 +348,7 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
331348
// Sanity check the resulting output values to make sure we
332349
// don't burn a great part to fees.
333350
totalOut := outputAmt + changeAmt
334-
err = sanityCheckFee(totalOut, totalSat-totalOut)
351+
err = sanityCheckFee(totalOut, totalSat-totalOut, maxFeeRatio)
335352
if err != nil {
336353
return nil, 0, 0, err
337354
}
@@ -347,8 +364,8 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
347364
reserved, dustLimit btcutil.Amount, coins []wallet.Coin,
348365
strategy wallet.CoinSelectionStrategy,
349366
existingWeight input.TxWeightEstimator,
350-
changeType ChangeAddressType) ([]wallet.Coin, btcutil.Amount,
351-
btcutil.Amount, error) {
367+
changeType ChangeAddressType, maxFeeRatio float64) ([]wallet.Coin,
368+
btcutil.Amount, btcutil.Amount, error) {
352369

353370
var (
354371
// selectSubtractFee is tracking if our coin selection was
@@ -369,7 +386,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
369386
// maxAmount with or without a change output that covers the miner fee.
370387
selected, changeAmt, err := CoinSelect(
371388
feeRate, maxAmount, dustLimit, coins, strategy, existingWeight,
372-
changeType,
389+
changeType, maxFeeRatio,
373390
)
374391

375392
var errInsufficientFunds *ErrInsufficientFunds
@@ -412,7 +429,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
412429
if selectSubtractFee {
413430
selected, outputAmount, changeAmt, err = CoinSelectSubtractFees(
414431
feeRate, totalBalance-reserved, dustLimit, coins,
415-
strategy, existingWeight, changeType,
432+
strategy, existingWeight, changeType, maxFeeRatio,
416433
)
417434
if err != nil {
418435
return nil, 0, 0, err
@@ -430,7 +447,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
430447

431448
return sum
432449
}
433-
err = sanityCheckFee(totalOut, sum(selected)-totalOut)
450+
err = sanityCheckFee(totalOut, sum(selected)-totalOut, maxFeeRatio)
434451
if err != nil {
435452
return nil, 0, 0, err
436453
}

lnwallet/chanfunding/coin_select_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func TestCoinSelect(t *testing.T) {
316316
selected, changeAmt, err := CoinSelect(
317317
feeRate, test.outputValue, dustLimit,
318318
test.coins, wallet.CoinSelectionLargest,
319-
fundingOutputEstimate, test.changeType,
319+
fundingOutputEstimate, test.changeType, 0,
320320
)
321321

322322
if test.expectErr {
@@ -428,7 +428,7 @@ func TestCalculateChangeAmount(t *testing.T) {
428428
changeAmt, needMore, err := CalculateChangeAmount(
429429
tc.totalInputAmt, tc.requiredAmt,
430430
tc.feeNoChange, tc.feeWithChange, tc.dustLimit,
431-
tc.changeType,
431+
tc.changeType, 0,
432432
)
433433

434434
if tc.expectErr != "" {
@@ -627,7 +627,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
627627
feeRate, test.spendValue, dustLimit, test.coins,
628628
wallet.CoinSelectionLargest,
629629
fundingOutputEstimate,
630-
defaultChanFundingChangeType,
630+
defaultChanFundingChangeType, 0,
631631
)
632632
if err != nil {
633633
switch {
@@ -872,7 +872,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
872872
test.reserved, dustLimit, test.coins,
873873
wallet.CoinSelectionLargest,
874874
fundingOutputEstimate,
875-
defaultChanFundingChangeType,
875+
defaultChanFundingChangeType, 0,
876876
)
877877
if len(test.expectErr) == 0 && err != nil {
878878
t.Fatal(err.Error())

lnwallet/chanfunding/wallet_assembler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
436436
reserve, w.cfg.DustLimit, coins,
437437
w.cfg.CoinSelectionStrategy,
438438
fundingOutputWeight, changeType,
439+
DefaultMaxFeeRatio,
439440
)
440441
if err != nil {
441442
return err
@@ -471,6 +472,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
471472
r.FeeRate, r.LocalAmt, dustLimit, coins,
472473
w.cfg.CoinSelectionStrategy,
473474
fundingOutputWeight, changeType,
475+
DefaultMaxFeeRatio,
474476
)
475477
if err != nil {
476478
return err
@@ -485,6 +487,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
485487
r.FeeRate, r.LocalAmt, dustLimit, coins,
486488
w.cfg.CoinSelectionStrategy,
487489
fundingOutputWeight, changeType,
490+
DefaultMaxFeeRatio,
488491
)
489492
if err != nil {
490493
return err

0 commit comments

Comments
 (0)