chainfee: fetch new relay fee from bitcoind

This commit adds a fetchMinMempoolFee function to the BitcoindEstimator
that fetches the current min mempool fee from the bitcoind backend. The
commit then also updates the BitcoindEstimator to use a minFeeManager
for it's minFeeManager member and uses the fetchMinMempoolFee function
to initialise this.
This commit is contained in:
Elle Mouton committed 2021-10-05 18:30:41 +02:00
1 parent c01699853d
commit 55077d9404
2 files changed
+39 -32

No files matched your search

+37 -32
View File
@@ -280,11 +280,11 @@ type BitcoindEstimator struct {
// produce fee estimates. // produce fee estimates.
fallbackFeePerKW SatPerKWeight fallbackFeePerKW SatPerKWeight
// minFeePerKW is the minimum fee, in sat/kw, that we should enforce. // minFeeManager is used to keep track of the minimum fee, in sat/kw,
// This will be used as the default fee rate for a transaction when the // that we should enforce. This will be used as the default fee rate
// estimated fee rate is too low to allow the transaction to propagate // for a transaction when the estimated fee rate is too low to allow
// through the network. // the transaction to propagate through the network.
minFeePerKW SatPerKWeight minFeeManager *minFeeManager
// feeMode is the estimate_mode to use when calling "estimatesmartfee". // feeMode is the estimate_mode to use when calling "estimatesmartfee".
// It can be either "ECONOMICAL" or "CONSERVATIVE", and it's default // It can be either "ECONOMICAL" or "CONSERVATIVE", and it's default
@@ -324,43 +324,47 @@ func NewBitcoindEstimator(rpcConfig rpcclient.ConnConfig, feeMode string,
// NOTE: This method is part of the Estimator interface. // NOTE: This method is part of the Estimator interface.
func (b *BitcoindEstimator) Start() error { func (b *BitcoindEstimator) Start() error {
// Once the connection to the backend node has been established, we'll // Once the connection to the backend node has been established, we'll
// query it for its minimum relay fee. Since the `getinfo` RPC has been // initialise the minimum relay fee manager which will query
// deprecated for `bitcoind`, we'll need to send a `getnetworkinfo` // the backend node for its minimum mempool fee.
// command as a raw request. relayFeeManager, err := newMinFeeManager(
resp, err := b.bitcoindConn.RawRequest("getnetworkinfo", nil) defaultUpdateInterval,
b.fetchMinMempoolFee,
)
if err != nil { if err != nil {
return err return err
} }
b.minFeeManager = relayFeeManager
// Parse the response to retrieve the relay fee in sat/KB. return nil
}
// fetchMinMempoolFee is used to fetch the minimum fee that the backend node
// requires for a tx to enter its mempool. The returned fee will be the
// maximum of the minimum relay fee and the minimum mempool fee.
func (b *BitcoindEstimator) fetchMinMempoolFee() (SatPerKWeight, error) {
resp, err := b.bitcoindConn.RawRequest("getmempoolinfo", nil)
if err != nil {
return 0, err
}
// Parse the response to retrieve the min mempool fee in sat/KB.
// mempoolminfee is the maximum of minrelaytxfee and
// minimum mempool fee
info := struct { info := struct {
RelayFee float64 `json:"relayfee"` MempoolMinFee float64 `json:"mempoolminfee"`
}{} }{}
if err := json.Unmarshal(resp, &info); err != nil { if err := json.Unmarshal(resp, &info); err != nil {
return err return 0, err
} }
relayFee, err := btcutil.NewAmount(info.RelayFee) minMempoolFee, err := btcutil.NewAmount(info.MempoolMinFee)
if err != nil { if err != nil {
return err return 0, err
} }
// The fee rate is expressed in sat/kb, so we'll manually convert it to // The fee rate is expressed in sat/kb, so we'll manually convert it to
// our desired sat/kw rate. // our desired sat/kw rate.
minRelayFeePerKw := SatPerKVByte(relayFee).FeePerKWeight() return SatPerKVByte(minMempoolFee).FeePerKWeight(), nil
// By default, we'll use the backend node's minimum relay fee as the
// minimum fee rate we'll propose for transacations. However, if this
// happens to be lower than our fee floor, we'll enforce that instead.
b.minFeePerKW = minRelayFeePerKw
if b.minFeePerKW < FeePerKwFloor {
b.minFeePerKW = FeePerKwFloor
}
log.Debugf("Using minimum fee rate of %v sat/kw",
int64(b.minFeePerKW))
return nil
} }
// Stop stops any spawned goroutines and cleans up the resources used // Stop stops any spawned goroutines and cleans up the resources used
@@ -406,7 +410,7 @@ func (b *BitcoindEstimator) EstimateFeePerKW(
// //
// NOTE: This method is part of the Estimator interface. // NOTE: This method is part of the Estimator interface.
func (b *BitcoindEstimator) RelayFeePerKW() SatPerKWeight { func (b *BitcoindEstimator) RelayFeePerKW() SatPerKWeight {
return b.minFeePerKW return b.minFeeManager.fetchMinFee()
} }
// fetchEstimate returns a fee estimate for a transaction to be confirmed in // fetchEstimate returns a fee estimate for a transaction to be confirmed in
@@ -453,12 +457,13 @@ func (b *BitcoindEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, err
satPerKw := SatPerKVByte(satPerKB).FeePerKWeight() satPerKw := SatPerKVByte(satPerKB).FeePerKWeight()
// Finally, we'll enforce our fee floor. // Finally, we'll enforce our fee floor.
if satPerKw < b.minFeePerKW { minRelayFee := b.minFeeManager.fetchMinFee()
if satPerKw < minRelayFee {
log.Debugf("Estimated fee rate of %v sat/kw is too low, "+ log.Debugf("Estimated fee rate of %v sat/kw is too low, "+
"using fee floor of %v sat/kw instead", satPerKw, "using fee floor of %v sat/kw instead", satPerKw,
b.minFeePerKW) minRelayFee)
satPerKw = b.minFeePerKW satPerKw = minRelayFee
} }
log.Debugf("Returning %v sat/kw for conf target of %v", log.Debugf("Returning %v sat/kw for conf target of %v",
+2
View File
@@ -5,6 +5,8 @@ import (
"time" "time"
) )
const defaultUpdateInterval = 10 * time.Minute
// minFeeManager is used to store and update the minimum fee that is required // 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 // 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. // that the backend used to fetch the fee is not queried too regularly.