diff --git a/lnwallet/fee_estimator.go b/lnwallet/fee_estimator.go index 3bdcdf661..3ff94d9ef 100644 --- a/lnwallet/fee_estimator.go +++ b/lnwallet/fee_estimator.go @@ -95,6 +95,12 @@ type BtcdFeeEstimator struct { // actually produce fee estimates. fallBackFeeRate SatPerVByte + // minFeeRate is the minimum relay fee, in sat/vbyte, of the backend + // node. This will be used as the default fee rate of a transaction when + // the estimated fee rate is too low to allow the transaction to + // propagate through the network. + minFeeRate SatPerVByte + btcdConn *rpcclient.Client } @@ -128,6 +134,22 @@ func (b *BtcdFeeEstimator) Start() error { return err } + // Once the connection to the backend node has been established, we'll + // query it for its minimum relay fee. + info, err := b.btcdConn.GetInfo() + if err != nil { + return err + } + + relayFee, err := btcutil.NewAmount(info.RelayFee) + if err != nil { + return err + } + + // The fee rate is expressed in sat/KB, so we'll manually convert it to + // our desired sat/vbyte rate. + b.minFeeRate = SatPerVByte(relayFee / 1000) + return nil } @@ -183,12 +205,20 @@ func (b *BtcdFeeEstimator) fetchEstimatePerVSize( // The value returned is expressed in fees per KB, while we want // fee-per-byte, so we'll divide by 1000 to map to satoshis-per-byte // before returning the estimate. - satPerByte := satPerKB / 1000 + satPerByte := SatPerVByte(satPerKB / 1000) + + // Before proceeding, we'll make sure that this fee rate respects the + // minimum relay fee set on the backend node. + if satPerByte < b.minFeeRate { + walletLog.Debugf("Using backend node's minimum relay fee rate "+ + "of %v sat/vbyte", b.minFeeRate) + satPerByte = b.minFeeRate + } walletLog.Debugf("Returning %v sat/vbyte for conf target of %v", int64(satPerByte), confTarget) - return SatPerVByte(satPerByte), nil + return satPerByte, nil } // A compile-time assertion to ensure that BtcdFeeEstimator implements the @@ -204,6 +234,12 @@ type BitcoindFeeEstimator struct { // actually produce fee estimates. fallBackFeeRate SatPerVByte + // minFeeRate is the minimum relay fee, in sat/vbyte, of the backend + // node. This will be used as the default fee rate of a transaction when + // the estimated fee rate is too low to allow the transaction to + // propagate through the network. + minFeeRate SatPerVByte + bitcoindConn *rpcclient.Client } @@ -235,6 +271,32 @@ func NewBitcoindFeeEstimator(rpcConfig rpcclient.ConnConfig, // // NOTE: This method is part of the FeeEstimator interface. func (b *BitcoindFeeEstimator) 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) + if err != nil { + return err + } + + // Parse the response to retrieve the relay fee in sat/KB. + info := struct { + RelayFee float64 `json:"relayfee"` + }{} + if err := json.Unmarshal(resp, &info); err != nil { + return err + } + + relayFee, err := btcutil.NewAmount(info.RelayFee) + if err != nil { + return err + } + + // The fee rate is expressed in sat/KB, so we'll manually convert it to + // our desired sat/vbyte rate. + b.minFeeRate = SatPerVByte(relayFee / 1000) + return nil } @@ -304,12 +366,20 @@ func (b *BitcoindFeeEstimator) fetchEstimatePerVSize( // The value returned is expressed in fees per KB, while we want // fee-per-byte, so we'll divide by 1000 to map to satoshis-per-byte // before returning the estimate. - satPerByte := satPerKB / 1000 + satPerByte := SatPerVByte(satPerKB / 1000) + + // Before proceeding, we'll make sure that this fee rate respects the + // minimum relay fee set on the backend node. + if satPerByte < b.minFeeRate { + walletLog.Debugf("Using backend node's minimum relay fee rate "+ + "of %v sat/vbyte", b.minFeeRate) + satPerByte = b.minFeeRate + } walletLog.Debugf("Returning %v sat/vbyte for conf target of %v", int64(satPerByte), confTarget) - return SatPerVByte(satPerByte), nil + return satPerByte, nil } // A compile-time assertion to ensure that BitcoindFeeEstimator implements the