lnwallet: add BtcdFeeEstimator implementation of FeeEstimator interface
In this commit, we add a new implementation of the FeeEstimator interface: the BtcdFeeEstimator. This implementation of the FeeEstimator is backed by an active bcd instance. Any requests to query for the current fee for a given confirmation target are proxied to this active bcd instance.
This commit is contained in:
parent
e20448ebc6
commit
78ccfb4989
@ -72,3 +72,120 @@ func (e StaticFeeEstimator) Stop() error {
|
||||
// A compile-time assertion to ensure that StaticFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*StaticFeeEstimator)(nil)
|
||||
|
||||
// BtcdFeeEstimator is an implementation of the FeeEstimator interface backed
|
||||
// by the RPC interface of an active btcd node. This implementation will proxy
|
||||
// any fee estimation requests to btcd's RPC interace.
|
||||
type BtcdFeeEstimator struct {
|
||||
// fallBackFeeRate is the fall back fee rate in satoshis per byte that
|
||||
// is returned if the fee estimator does not yet have enough data to
|
||||
// actually produce fee estimates.
|
||||
fallBackFeeRate btcutil.Amount
|
||||
|
||||
btcdConn *rpcclient.Client
|
||||
}
|
||||
|
||||
// NewBtcdFeeEstimator creates a new BtcdFeeEstimator given a fully populated
|
||||
// rpc config that is able to successfully connect and authenticate with the
|
||||
// btcd node, and also a fall back fee rate. The fallback fee rate is used in
|
||||
// the occasion that the estimator has insufficient data, or returns zero for a
|
||||
// fee estimate.
|
||||
func NewBtcdFeeEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
fallBackFeeRate btcutil.Amount) (*BtcdFeeEstimator, error) {
|
||||
|
||||
rpcConfig.DisableConnectOnNew = true
|
||||
rpcConfig.DisableAutoReconnect = false
|
||||
chainConn, err := rpcclient.New(&rpcConfig, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &BtcdFeeEstimator{
|
||||
fallBackFeeRate: fallBackFeeRate,
|
||||
btcdConn: chainConn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines
|
||||
// it needs to perform its duty.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BtcdFeeEstimator) Start() error {
|
||||
if err := b.btcdConn.Connect(20); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops any spawned goroutines and cleans up the resources used
|
||||
// by the fee estimator.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BtcdFeeEstimator) Stop() error {
|
||||
b.btcdConn.Shutdown()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EstimateFeePerByte takes in a target for the number of blocks until an
|
||||
// initial confirmation and returns the estimated fee expressed in
|
||||
// satoshis/byte.
|
||||
func (b *BtcdFeeEstimator) EstimateFeePerByte(numBlocks uint32) (btcutil.Amount, error) {
|
||||
feeEstimate, err := b.fetchEstimatePerByte(numBlocks)
|
||||
switch {
|
||||
// If the estimator doesn't have enough data, or returns an error, then
|
||||
// to return a proper value, then we'll return the default fall back
|
||||
// fee rate.
|
||||
case err != nil:
|
||||
walletLog.Errorf("unable to query estimator: %v", err)
|
||||
fallthrough
|
||||
|
||||
case feeEstimate == 0:
|
||||
return b.fallBackFeeRate, nil
|
||||
}
|
||||
|
||||
return feeEstimate, nil
|
||||
}
|
||||
|
||||
// EstimateFeePerWeight takes in a target for the number of blocks until an
|
||||
// initial confirmation and returns the estimated fee expressed in
|
||||
// satoshis/weight.
|
||||
func (b *BtcdFeeEstimator) EstimateFeePerWeight(numBlocks uint32) (btcutil.Amount, error) {
|
||||
feePerByte, err := b.EstimateFeePerByte(numBlocks)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// We'll scale down the fee per byte to fee per weight, as for each raw
|
||||
// byte, there's 1/4 unit of weight mapped to it.
|
||||
return btcutil.Amount(feePerByte / blockchain.WitnessScaleFactor), nil
|
||||
}
|
||||
|
||||
// fetchEstimate returns a fee estimate for a transaction be be confirmed in
|
||||
// confTarget blocks. The estimate is returned in sat/byte.
|
||||
func (b *BtcdFeeEstimator) fetchEstimatePerByte(confTarget uint32) (btcutil.Amount, error) {
|
||||
// First, we'll fetch the estimate for our confirmation target.
|
||||
btcPerKB, err := b.btcdConn.EstimateFee(int64(confTarget))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Next, we'll convert the returned value to satoshis, as it's
|
||||
// currently returned in BTC.
|
||||
satPerKB := uint64(btcPerKB * 10e8)
|
||||
|
||||
// The value returned is expressed in fees per KB, while we want
|
||||
// fee-per-byte, so we'll divide by 1024 to map to satoshis-per-byte
|
||||
// before returning the estimate.
|
||||
satPerByte := btcutil.Amount(satPerKB / 1024)
|
||||
|
||||
walletLog.Debugf("Returning %v sat/byte for conf target of %v",
|
||||
int64(satPerByte), confTarget)
|
||||
|
||||
return satPerByte, nil
|
||||
}
|
||||
|
||||
// A compile-time assertion to ensure that BtcdFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*BtcdFeeEstimator)(nil)
|
||||
|
Loading…
Reference in New Issue
Block a user