mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
2449e66d29
The minimum relay fee is always ensured to be above our fee floor except in the very first min relay fee query to bitcoind. This commit ensures that the fee floor is respected in this first query.
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package chainfee
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const defaultUpdateInterval = 10 * time.Minute
|
|
|
|
// minFeeManager is used to store and update the minimum fee that is required
|
|
// by a transaction to be accepted to the mempool. The minFeeManager ensures
|
|
// that the backend used to fetch the fee is not queried too regularly.
|
|
type minFeeManager struct {
|
|
mu sync.Mutex
|
|
minFeePerKW SatPerKWeight
|
|
lastUpdatedTime time.Time
|
|
minUpdateInterval time.Duration
|
|
fetchFeeFunc fetchFee
|
|
}
|
|
|
|
// fetchFee represents a function that can be used to fetch a fee.
|
|
type fetchFee func() (SatPerKWeight, error)
|
|
|
|
// newMinFeeManager creates a new minFeeManager and uses the
|
|
// given fetchMinFee function to set the minFeePerKW of the minFeeManager.
|
|
// This function requires the fetchMinFee function to succeed.
|
|
func newMinFeeManager(minUpdateInterval time.Duration,
|
|
fetchMinFee fetchFee) (*minFeeManager, error) {
|
|
|
|
minFee, err := fetchMinFee()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Ensure that the minimum fee we use is always clamped by our fee
|
|
// floor.
|
|
if minFee < FeePerKwFloor {
|
|
minFee = FeePerKwFloor
|
|
}
|
|
|
|
return &minFeeManager{
|
|
minFeePerKW: minFee,
|
|
lastUpdatedTime: time.Now(),
|
|
minUpdateInterval: minUpdateInterval,
|
|
fetchFeeFunc: fetchMinFee,
|
|
}, nil
|
|
}
|
|
|
|
// fetchMinFee returns the stored minFeePerKW if it has been updated recently
|
|
// or if the call to the chain backend fails. Otherwise, it sets the stored
|
|
// minFeePerKW to the fee returned from the backend and floors it based on
|
|
// our fee floor.
|
|
func (m *minFeeManager) fetchMinFee() SatPerKWeight {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if time.Since(m.lastUpdatedTime) < m.minUpdateInterval {
|
|
return m.minFeePerKW
|
|
}
|
|
|
|
newMinFee, err := m.fetchFeeFunc()
|
|
if err != nil {
|
|
log.Errorf("Unable to fetch updated min fee from chain "+
|
|
"backend. Using last known min fee instead: %v", err)
|
|
|
|
return m.minFeePerKW
|
|
}
|
|
|
|
// By default, we'll use the backend node's minimum fee as the
|
|
// minimum fee rate we'll propose for transactions. However, if this
|
|
// happens to be lower than our fee floor, we'll enforce that instead.
|
|
m.minFeePerKW = newMinFee
|
|
if m.minFeePerKW < FeePerKwFloor {
|
|
m.minFeePerKW = FeePerKwFloor
|
|
}
|
|
m.lastUpdatedTime = time.Now()
|
|
|
|
log.Debugf("Using minimum fee rate of %v sat/kw",
|
|
int64(m.minFeePerKW))
|
|
|
|
return m.minFeePerKW
|
|
}
|