lnwallet+sweep: cap conf target used in fee estimator

This commit is contained in:
yyforyongyu 2024-03-18 10:56:41 +08:00
parent 1fa8ca72ee
commit 0fc5301d12
No known key found for this signature in database
GPG key ID: 9BCD95C4FF296868
3 changed files with 35 additions and 7 deletions

View file

@ -17,11 +17,11 @@ import (
) )
const ( const (
// maxBlockTarget is the highest number of blocks confirmations that // MaxBlockTarget is the highest number of blocks confirmations that
// a WebAPIEstimator will cache fees for. This number is chosen // a WebAPIEstimator will cache fees for. This number is chosen
// because it's the highest number of confs bitcoind will return a fee // because it's the highest number of confs bitcoind will return a fee
// estimate for. // estimate for.
maxBlockTarget uint32 = 1008 MaxBlockTarget uint32 = 1008
// minBlockTarget is the lowest number of blocks confirmations that // minBlockTarget is the lowest number of blocks confirmations that
// a WebAPIEstimator will cache fees for. Requesting an estimate for // a WebAPIEstimator will cache fees for. Requesting an estimate for
@ -463,11 +463,11 @@ func (b *BitcoindEstimator) Stop() error {
func (b *BitcoindEstimator) EstimateFeePerKW( func (b *BitcoindEstimator) EstimateFeePerKW(
numBlocks uint32) (SatPerKWeight, error) { numBlocks uint32) (SatPerKWeight, error) {
if numBlocks > maxBlockTarget { if numBlocks > MaxBlockTarget {
log.Debugf("conf target %d exceeds the max value, "+ log.Debugf("conf target %d exceeds the max value, "+
"use %d instead.", numBlocks, maxBlockTarget, "use %d instead.", numBlocks, MaxBlockTarget,
) )
numBlocks = maxBlockTarget numBlocks = MaxBlockTarget
} }
feeEstimate, err := b.fetchEstimate(numBlocks, b.feeMode) feeEstimate, err := b.fetchEstimate(numBlocks, b.feeMode)
@ -761,8 +761,8 @@ func NewWebAPIEstimator(api WebAPIFeeSource, noCache bool) *WebAPIEstimator {
func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) ( func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) (
SatPerKWeight, error) { SatPerKWeight, error) {
if numBlocks > maxBlockTarget { if numBlocks > MaxBlockTarget {
numBlocks = maxBlockTarget numBlocks = MaxBlockTarget
} else if numBlocks < minBlockTarget { } else if numBlocks < minBlockTarget {
return 0, fmt.Errorf("conf target of %v is too low, minimum "+ return 0, fmt.Errorf("conf target of %v is too low, minimum "+
"accepted is %v", numBlocks, minBlockTarget) "accepted is %v", numBlocks, minBlockTarget)

View file

@ -276,6 +276,16 @@ func (l *LinearFeeFunction) estimateFeeRate(
ConfTarget: confTarget, ConfTarget: confTarget,
} }
// If the conf target is greater or equal to the max allowed value
// (1008), we will use the min relay fee instead.
if confTarget >= chainfee.MaxBlockTarget {
minFeeRate := l.estimator.RelayFeePerKW()
log.Debugf("Conf target %v is greater than max block target, "+
"using min relay fee rate %v", confTarget, minFeeRate)
return minFeeRate, nil
}
// endingFeeRate comes from budget/txWeight, which means the returned // endingFeeRate comes from budget/txWeight, which means the returned
// fee rate will always be capped by this value, hence we don't need to // fee rate will always be capped by this value, hence we don't need to
// worry about overpay. // worry about overpay.

View file

@ -19,6 +19,7 @@ func TestLinearFeeFunctionNew(t *testing.T) {
// Create testing params. // Create testing params.
maxFeeRate := chainfee.SatPerKWeight(10000) maxFeeRate := chainfee.SatPerKWeight(10000)
estimatedFeeRate := chainfee.SatPerKWeight(500) estimatedFeeRate := chainfee.SatPerKWeight(500)
minRelayFeeRate := chainfee.SatPerKWeight(100)
confTarget := uint32(6) confTarget := uint32(6)
// Assert init fee function with zero conf value returns an error. // Assert init fee function with zero conf value returns an error.
@ -62,6 +63,23 @@ func TestLinearFeeFunctionNew(t *testing.T) {
rt.ErrorContains(err, "fee rate delta is zero") rt.ErrorContains(err, "fee rate delta is zero")
rt.Nil(f) rt.Nil(f)
// When the conf target is >= 1008, the min relay fee should be used.
//
// Mock the fee estimator to reutrn the fee rate.
estimator.On("RelayFeePerKW").Return(minRelayFeeRate).Once()
largeConf := uint32(1008)
f, err = NewLinearFeeFunction(maxFeeRate, largeConf, estimator)
rt.NoError(err)
rt.NotNil(f)
// Assert the internal state.
rt.Equal(minRelayFeeRate, f.startingFeeRate)
rt.Equal(maxFeeRate, f.endingFeeRate)
rt.Equal(minRelayFeeRate, f.currentFeeRate)
rt.NotZero(f.deltaFeeRate)
rt.Equal(largeConf, f.width)
// Check a successfully created fee function. // Check a successfully created fee function.
// //
// Mock the fee estimator to return the fee rate. // Mock the fee estimator to return the fee rate.