mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 14:22:37 +01:00
sweep: increase delta fee rate precision in fee function
This commit adds a private type `mSatPerKWeight` that expresses a given fee rate in millisatoshi per kw. This is needed to increase the precision of the fee function. When sweeping anchor inputs, if using a deadline delta of over 1000, it's likely the delta will be 0 sat/kw due to precision.
This commit is contained in:
parent
23feef7e6c
commit
7fb18bc0d5
2 changed files with 32 additions and 9 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -14,6 +15,17 @@ var (
|
|||
ErrMaxPosition = errors.New("position already at max")
|
||||
)
|
||||
|
||||
// mSatPerKWeight represents a fee rate in msat/kw.
|
||||
//
|
||||
// TODO(yy): unify all the units to be virtual bytes.
|
||||
type mSatPerKWeight lnwire.MilliSatoshi
|
||||
|
||||
// String returns a human-readable string of the fee rate.
|
||||
func (m mSatPerKWeight) String() string {
|
||||
s := lnwire.MilliSatoshi(m)
|
||||
return fmt.Sprintf("%v/kw", s)
|
||||
}
|
||||
|
||||
// FeeFunction defines an interface that is used to calculate fee rates for
|
||||
// transactions. It's expected the implementations use three params, the
|
||||
// starting fee rate, the ending fee rate, and number of blocks till deadline
|
||||
|
@ -80,8 +92,10 @@ type LinearFeeFunction struct {
|
|||
// and the current block height.
|
||||
position uint32
|
||||
|
||||
// deltaFeeRate is the fee rate increase per block.
|
||||
deltaFeeRate chainfee.SatPerKWeight
|
||||
// deltaFeeRate is the fee rate (msat/kw) increase per block.
|
||||
//
|
||||
// NOTE: this is used to increase precision.
|
||||
deltaFeeRate mSatPerKWeight
|
||||
|
||||
// estimator is the fee estimator used to estimate the fee rate. We use
|
||||
// it to get the initial fee rate and, use it as a benchmark to decide
|
||||
|
@ -121,21 +135,28 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, confTarget uint32,
|
|||
|
||||
// Calculate how much fee rate should be increased per block.
|
||||
end := l.endingFeeRate
|
||||
delta := btcutil.Amount(end - start).MulF64(1 / float64(confTarget))
|
||||
|
||||
// The starting and ending fee rates are in sat/kw, so we need to
|
||||
// convert them to msat/kw by multiplying by 1000.
|
||||
delta := btcutil.Amount(end - start).MulF64(1000 / float64(confTarget))
|
||||
l.deltaFeeRate = mSatPerKWeight(delta)
|
||||
|
||||
// We only allow the delta to be zero if the width is one - when the
|
||||
// delta is zero, it means the starting and ending fee rates are the
|
||||
// same, which means there's nothing to increase, so any width greater
|
||||
// than 1 doesn't provide any utility. This could happen when the
|
||||
// sweeper is offered to sweep an input that has passed its deadline.
|
||||
if delta == 0 && l.width != 1 {
|
||||
if l.deltaFeeRate == 0 && l.width != 1 {
|
||||
log.Errorf("Failed to init fee function: startingFeeRate=%v, "+
|
||||
"endingFeeRate=%v, width=%v, delta=%v", start, end,
|
||||
confTarget, l.deltaFeeRate)
|
||||
|
||||
return nil, fmt.Errorf("fee rate delta is zero")
|
||||
}
|
||||
|
||||
// Attach the calculated values to the fee function.
|
||||
l.startingFeeRate = start
|
||||
l.currentFeeRate = start
|
||||
l.deltaFeeRate = chainfee.SatPerKWeight(delta)
|
||||
|
||||
log.Debugf("Linear fee function initialized with startingFeeRate=%v, "+
|
||||
"endingFeeRate=%v, width=%v, delta=%v", start, end,
|
||||
|
@ -234,7 +255,9 @@ func (l *LinearFeeFunction) feeRateAtPosition(p uint32) chainfee.SatPerKWeight {
|
|||
return l.endingFeeRate
|
||||
}
|
||||
|
||||
feeRateDelta := btcutil.Amount(l.deltaFeeRate).MulF64(float64(p))
|
||||
// deltaFeeRate is in msat/kw, so we need to divide by 1000 to get the
|
||||
// fee rate in sat/kw.
|
||||
feeRateDelta := btcutil.Amount(l.deltaFeeRate).MulF64(float64(p) / 1000)
|
||||
|
||||
feeRate := l.startingFeeRate + chainfee.SatPerKWeight(feeRateDelta)
|
||||
if feeRate > l.endingFeeRate {
|
||||
|
|
|
@ -54,8 +54,8 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||
//
|
||||
// Mock the fee estimator to return the fee rate.
|
||||
estimator.On("EstimateFeePerKW", confTarget).Return(
|
||||
// The starting fee rate is 1 sat/kw less than the max fee rate.
|
||||
maxFeeRate-1, nil).Once()
|
||||
// The starting fee rate is the max fee rate.
|
||||
maxFeeRate, nil).Once()
|
||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||
|
||||
f, err = NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
||||
|
@ -96,7 +96,7 @@ func TestLinearFeeFunctionFeeRateAtPosition(t *testing.T) {
|
|||
startingFeeRate: 1000,
|
||||
endingFeeRate: 3000,
|
||||
position: 0,
|
||||
deltaFeeRate: 1000,
|
||||
deltaFeeRate: 1_000_000,
|
||||
width: 3,
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue