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.
fallbackFeePerKW SatPerKWeight
// minFeePerKW is the minimum fee, in sat/kw, that we should enforce.
// This will be used as the default fee rate for a transaction when the
// estimated fee rate is too low to allow the transaction to propagate
// through the network.
minFeePerKW SatPerKWeight
// minFeeManager is used to keep track of the minimum fee, in sat/kw,
// that we should enforce. This will be used as the default fee rate
// for a transaction when the estimated fee rate is too low to allow
// the transaction to propagate through the network.
minFeeManager *minFeeManager
// feeMode is the estimate_mode to use when calling "estimatesmartfee".
// 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.
func (b *BitcoindEstimator) Start() error {
// 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
// deprecated for `bitcoind`, we'll need to send a `getnetworkinfo`
// command as a raw request.
resp, err := b.bitcoindConn.RawRequest("getnetworkinfo", nil)
// initialise the minimum relay fee manager which will query
// the backend node for its minimum mempool fee.
relayFeeManager, err := newMinFeeManager(
defaultUpdateInterval,
b.fetchMinMempoolFee,
)
if err != nil {
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 {
RelayFee float64 `json:"relayfee"`
MempoolMinFee float64 `json:"mempoolminfee"`
}{}
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 {
return err
return 0, err
}
// The fee rate is expressed in sat/kb, so we'll manually convert it to
// our desired sat/kw rate.
minRelayFeePerKw := SatPerKVByte(relayFee).FeePerKWeight()
// 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
return SatPerKVByte(minMempoolFee).FeePerKWeight(), nil
}
// 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.
func (b *BitcoindEstimator) RelayFeePerKW() SatPerKWeight {
return b.minFeePerKW
return b.minFeeManager.fetchMinFee()
}
// 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()
// 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, "+
"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",
+2
View File
@@ -5,6 +5,8 @@ import (
"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.