Merge pull request #3653 from Roasbeef/external-funding-chainfees
chainfees: create new chainfees package extracting fees from lnwallet
This commit is contained in:
47 files changed
+536
-400
No files matched your search
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -289,7 +290,7 @@ func (b *BtcWallet) IsOurAddress(a btcutil.Address) bool {
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate lnwallet.SatPerKWeight) (*wire.MsgTx, error) {
|
||||
feeRate chainfee.SatPerKWeight) (*wire.MsgTx, error) {
|
||||
|
||||
// Convert our fee rate from sat/kw to sat/kb since it's required by
|
||||
// SendOutputs.
|
||||
@@ -314,7 +315,7 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
|
||||
feeRate lnwallet.SatPerKWeight, dryRun bool) (*txauthor.AuthoredTx, error) {
|
||||
feeRate chainfee.SatPerKWeight, dryRun bool) (*txauthor.AuthoredTx, error) {
|
||||
|
||||
// The fee rate is passed in using units of sat/kw, so we'll convert
|
||||
// this to sat/KB as the CreateSimpleTx method requires this unit.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package lnwallet
|
||||
package chainfee
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -10,85 +10,41 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// FeePerKwFloor is the lowest fee rate in sat/kw that we should use for
|
||||
// determining transaction fees.
|
||||
FeePerKwFloor SatPerKWeight = 253
|
||||
|
||||
// maxBlockTarget is the highest number of blocks confirmations that
|
||||
// a WebAPIFeeEstimator will cache fees for. This number is chosen
|
||||
// a WebAPIEstimator will cache fees for. This number is chosen
|
||||
// because it's the highest number of confs bitcoind will return a fee
|
||||
// estimate for.
|
||||
maxBlockTarget uint32 = 1009
|
||||
|
||||
// minBlockTarget is the lowest number of blocks confirmations that
|
||||
// a WebAPIFeeEstimator will cache fees for. Requesting an estimate for
|
||||
// a WebAPIEstimator will cache fees for. Requesting an estimate for
|
||||
// less than this will result in an error.
|
||||
minBlockTarget uint32 = 2
|
||||
|
||||
// minFeeUpdateTimeout represents the minimum interval in which a
|
||||
// WebAPIFeeEstimator will request fresh fees from its API.
|
||||
// WebAPIEstimator will request fresh fees from its API.
|
||||
minFeeUpdateTimeout = 5 * time.Minute
|
||||
|
||||
// maxFeeUpdateTimeout represents the maximum interval in which a
|
||||
// WebAPIFeeEstimator will request fresh fees from its API.
|
||||
// WebAPIEstimator will request fresh fees from its API.
|
||||
maxFeeUpdateTimeout = 20 * time.Minute
|
||||
)
|
||||
|
||||
// SatPerKVByte represents a fee rate in sat/kb.
|
||||
type SatPerKVByte btcutil.Amount
|
||||
|
||||
// FeeForVSize calculates the fee resulting from this fee rate and the given
|
||||
// vsize in vbytes.
|
||||
func (s SatPerKVByte) FeeForVSize(vbytes int64) btcutil.Amount {
|
||||
return btcutil.Amount(s) * btcutil.Amount(vbytes) / 1000
|
||||
}
|
||||
|
||||
// FeePerKWeight converts the current fee rate from sat/kb to sat/kw.
|
||||
func (s SatPerKVByte) FeePerKWeight() SatPerKWeight {
|
||||
return SatPerKWeight(s / blockchain.WitnessScaleFactor)
|
||||
}
|
||||
|
||||
// String returns a human-readable string of the fee rate.
|
||||
func (s SatPerKVByte) String() string {
|
||||
return fmt.Sprintf("%v sat/kb", int64(s))
|
||||
}
|
||||
|
||||
// SatPerKWeight represents a fee rate in sat/kw.
|
||||
type SatPerKWeight btcutil.Amount
|
||||
|
||||
// FeeForWeight calculates the fee resulting from this fee rate and the given
|
||||
// weight in weight units (wu).
|
||||
func (s SatPerKWeight) FeeForWeight(wu int64) btcutil.Amount {
|
||||
// The resulting fee is rounded down, as specified in BOLT#03.
|
||||
return btcutil.Amount(s) * btcutil.Amount(wu) / 1000
|
||||
}
|
||||
|
||||
// FeePerKVByte converts the current fee rate from sat/kw to sat/kb.
|
||||
func (s SatPerKWeight) FeePerKVByte() SatPerKVByte {
|
||||
return SatPerKVByte(s * blockchain.WitnessScaleFactor)
|
||||
}
|
||||
|
||||
// String returns a human-readable string of the fee rate.
|
||||
func (s SatPerKWeight) String() string {
|
||||
return fmt.Sprintf("%v sat/kw", int64(s))
|
||||
}
|
||||
|
||||
// FeeEstimator provides the ability to estimate on-chain transaction fees for
|
||||
// Estimator provides the ability to estimate on-chain transaction fees for
|
||||
// various combinations of transaction sizes and desired confirmation time
|
||||
// (measured by number of blocks).
|
||||
type FeeEstimator interface {
|
||||
type Estimator interface {
|
||||
// EstimateFeePerKW takes in a target for the number of blocks until an
|
||||
// initial confirmation and returns the estimated fee expressed in
|
||||
// sat/kw.
|
||||
EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error)
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines
|
||||
// Start signals the Estimator to start any processes or goroutines
|
||||
// it needs to perform its duty.
|
||||
Start() error
|
||||
|
||||
@@ -102,11 +58,11 @@ type FeeEstimator interface {
|
||||
RelayFeePerKW() SatPerKWeight
|
||||
}
|
||||
|
||||
// StaticFeeEstimator will return a static value for all fee calculation
|
||||
// requests. It is designed to be replaced by a proper fee calculation
|
||||
// implementation. The fees are not accessible directly, because changing them
|
||||
// would not be thread safe.
|
||||
type StaticFeeEstimator struct {
|
||||
// StaticEstimator will return a static value for all fee calculation requests.
|
||||
// It is designed to be replaced by a proper fee calculation implementation.
|
||||
// The fees are not accessible directly, because changing them would not be
|
||||
// thread safe.
|
||||
type StaticEstimator struct {
|
||||
// feePerKW is the static fee rate in satoshis-per-vbyte that will be
|
||||
// returned by this fee estimator.
|
||||
feePerKW SatPerKWeight
|
||||
@@ -116,11 +72,10 @@ type StaticFeeEstimator struct {
|
||||
relayFee SatPerKWeight
|
||||
}
|
||||
|
||||
// NewStaticFeeEstimator returns a new static fee estimator instance.
|
||||
func NewStaticFeeEstimator(feePerKW,
|
||||
relayFee SatPerKWeight) *StaticFeeEstimator {
|
||||
// NewStaticEstimator returns a new static fee estimator instance.
|
||||
func NewStaticEstimator(feePerKW, relayFee SatPerKWeight) *StaticEstimator {
|
||||
|
||||
return &StaticFeeEstimator{
|
||||
return &StaticEstimator{
|
||||
feePerKW: feePerKW,
|
||||
relayFee: relayFee,
|
||||
}
|
||||
@@ -128,43 +83,43 @@ func NewStaticFeeEstimator(feePerKW,
|
||||
|
||||
// EstimateFeePerKW will return a static value for fee calculations.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (e StaticFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (e StaticEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
return e.feePerKW, nil
|
||||
}
|
||||
|
||||
// RelayFeePerKW returns the minimum fee rate required for transactions to be
|
||||
// relayed.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (e StaticFeeEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (e StaticEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
return e.relayFee
|
||||
}
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines
|
||||
// Start signals the Estimator to start any processes or goroutines
|
||||
// it needs to perform its duty.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (e StaticFeeEstimator) Start() error {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (e StaticEstimator) Start() error {
|
||||
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 (e StaticFeeEstimator) Stop() error {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (e StaticEstimator) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// A compile-time assertion to ensure that StaticFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*StaticFeeEstimator)(nil)
|
||||
// Estimator interface.
|
||||
var _ Estimator = (*StaticEstimator)(nil)
|
||||
|
||||
// BtcdFeeEstimator is an implementation of the FeeEstimator interface backed
|
||||
// BtcdEstimator is an implementation of the Estimator interface backed
|
||||
// by the RPC interface of an active btcd node. This implementation will proxy
|
||||
// any fee estimation requests to btcd's RPC interface.
|
||||
type BtcdFeeEstimator struct {
|
||||
type BtcdEstimator struct {
|
||||
// fallbackFeePerKW is the fall back fee rate in sat/kw that is returned
|
||||
// if the fee estimator does not yet have enough data to actually
|
||||
// produce fee estimates.
|
||||
@@ -179,13 +134,13 @@ type BtcdFeeEstimator struct {
|
||||
btcdConn *rpcclient.Client
|
||||
}
|
||||
|
||||
// NewBtcdFeeEstimator creates a new BtcdFeeEstimator given a fully populated
|
||||
// NewBtcdEstimator creates a new BtcdEstimator 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 SatPerKWeight) (*BtcdFeeEstimator, error) {
|
||||
func NewBtcdEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
fallBackFeeRate SatPerKWeight) (*BtcdEstimator, error) {
|
||||
|
||||
rpcConfig.DisableConnectOnNew = true
|
||||
rpcConfig.DisableAutoReconnect = false
|
||||
@@ -194,17 +149,17 @@ func NewBtcdFeeEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &BtcdFeeEstimator{
|
||||
return &BtcdEstimator{
|
||||
fallbackFeePerKW: fallBackFeeRate,
|
||||
btcdConn: chainConn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines
|
||||
// Start signals the Estimator 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 {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BtcdEstimator) Start() error {
|
||||
if err := b.btcdConn.Connect(20); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -233,7 +188,7 @@ func (b *BtcdFeeEstimator) Start() error {
|
||||
b.minFeePerKW = FeePerKwFloor
|
||||
}
|
||||
|
||||
walletLog.Debugf("Using minimum fee rate of %v sat/kw",
|
||||
log.Debugf("Using minimum fee rate of %v sat/kw",
|
||||
int64(b.minFeePerKW))
|
||||
|
||||
return nil
|
||||
@@ -242,8 +197,8 @@ func (b *BtcdFeeEstimator) Start() error {
|
||||
// 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 {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BtcdEstimator) Stop() error {
|
||||
b.btcdConn.Shutdown()
|
||||
|
||||
return nil
|
||||
@@ -252,15 +207,15 @@ func (b *BtcdFeeEstimator) Stop() error {
|
||||
// EstimateFeePerKW takes in a target for the number of blocks until an initial
|
||||
// confirmation and returns the estimated fee expressed in sat/kw.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BtcdFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BtcdEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
feeEstimate, err := b.fetchEstimate(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)
|
||||
log.Errorf("unable to query estimator: %v", err)
|
||||
fallthrough
|
||||
|
||||
case feeEstimate == 0:
|
||||
@@ -273,14 +228,14 @@ func (b *BtcdFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, er
|
||||
// RelayFeePerKW returns the minimum fee rate required for transactions to be
|
||||
// relayed.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BtcdFeeEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BtcdEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
return b.minFeePerKW
|
||||
}
|
||||
|
||||
// fetchEstimate returns a fee estimate for a transaction to be confirmed in
|
||||
// confTarget blocks. The estimate is returned in sat/kw.
|
||||
func (b *BtcdFeeEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, error) {
|
||||
func (b *BtcdEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, error) {
|
||||
// First, we'll fetch the estimate for our confirmation target.
|
||||
btcPerKB, err := b.btcdConn.EstimateFee(int64(confTarget))
|
||||
if err != nil {
|
||||
@@ -300,26 +255,26 @@ func (b *BtcdFeeEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, erro
|
||||
|
||||
// Finally, we'll enforce our fee floor.
|
||||
if satPerKw < b.minFeePerKW {
|
||||
walletLog.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,
|
||||
b.minFeePerKW)
|
||||
satPerKw = b.minFeePerKW
|
||||
}
|
||||
|
||||
walletLog.Debugf("Returning %v sat/kw for conf target of %v",
|
||||
log.Debugf("Returning %v sat/kw for conf target of %v",
|
||||
int64(satPerKw), confTarget)
|
||||
|
||||
return satPerKw, nil
|
||||
}
|
||||
|
||||
// A compile-time assertion to ensure that BtcdFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*BtcdFeeEstimator)(nil)
|
||||
// A compile-time assertion to ensure that BtcdEstimator implements the
|
||||
// Estimator interface.
|
||||
var _ Estimator = (*BtcdEstimator)(nil)
|
||||
|
||||
// BitcoindFeeEstimator is an implementation of the FeeEstimator interface
|
||||
// backed by the RPC interface of an active bitcoind node. This implementation
|
||||
// will proxy any fee estimation requests to bitcoind's RPC interface.
|
||||
type BitcoindFeeEstimator struct {
|
||||
// BitcoindEstimator is an implementation of the Estimator interface backed by
|
||||
// the RPC interface of an active bitcoind node. This implementation will proxy
|
||||
// any fee estimation requests to bitcoind's RPC interface.
|
||||
type BitcoindEstimator struct {
|
||||
// fallbackFeePerKW is the fallback fee rate in sat/kw that is returned
|
||||
// if the fee estimator does not yet have enough data to actually
|
||||
// produce fee estimates.
|
||||
@@ -334,13 +289,13 @@ type BitcoindFeeEstimator struct {
|
||||
bitcoindConn *rpcclient.Client
|
||||
}
|
||||
|
||||
// NewBitcoindFeeEstimator creates a new BitcoindFeeEstimator given a fully
|
||||
// populated rpc config that is able to successfully connect and authenticate
|
||||
// with the bitcoind 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 NewBitcoindFeeEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
fallBackFeeRate SatPerKWeight) (*BitcoindFeeEstimator, error) {
|
||||
// NewBitcoindEstimator creates a new BitcoindEstimator given a fully populated
|
||||
// rpc config that is able to successfully connect and authenticate with the
|
||||
// bitcoind 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 NewBitcoindEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
fallBackFeeRate SatPerKWeight) (*BitcoindEstimator, error) {
|
||||
|
||||
rpcConfig.DisableConnectOnNew = true
|
||||
rpcConfig.DisableAutoReconnect = false
|
||||
@@ -351,17 +306,17 @@ func NewBitcoindFeeEstimator(rpcConfig rpcclient.ConnConfig,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &BitcoindFeeEstimator{
|
||||
return &BitcoindEstimator{
|
||||
fallbackFeePerKW: fallBackFeeRate,
|
||||
bitcoindConn: chainConn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines
|
||||
// Start signals the Estimator to start any processes or goroutines
|
||||
// it needs to perform its duty.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BitcoindFeeEstimator) Start() error {
|
||||
// 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`
|
||||
@@ -396,7 +351,7 @@ func (b *BitcoindFeeEstimator) Start() error {
|
||||
b.minFeePerKW = FeePerKwFloor
|
||||
}
|
||||
|
||||
walletLog.Debugf("Using minimum fee rate of %v sat/kw",
|
||||
log.Debugf("Using minimum fee rate of %v sat/kw",
|
||||
int64(b.minFeePerKW))
|
||||
|
||||
return nil
|
||||
@@ -405,23 +360,23 @@ func (b *BitcoindFeeEstimator) Start() error {
|
||||
// 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 *BitcoindFeeEstimator) Stop() error {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BitcoindEstimator) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EstimateFeePerKW takes in a target for the number of blocks until an initial
|
||||
// confirmation and returns the estimated fee expressed in sat/kw.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BitcoindFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BitcoindEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
feeEstimate, err := b.fetchEstimate(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)
|
||||
log.Errorf("unable to query estimator: %v", err)
|
||||
fallthrough
|
||||
|
||||
case feeEstimate == 0:
|
||||
@@ -434,14 +389,14 @@ func (b *BitcoindFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight
|
||||
// RelayFeePerKW returns the minimum fee rate required for transactions to be
|
||||
// relayed.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (b *BitcoindFeeEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (b *BitcoindEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
return b.minFeePerKW
|
||||
}
|
||||
|
||||
// fetchEstimate returns a fee estimate for a transaction to be confirmed in
|
||||
// confTarget blocks. The estimate is returned in sat/kw.
|
||||
func (b *BitcoindFeeEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, error) {
|
||||
func (b *BitcoindEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, error) {
|
||||
// First, we'll send an "estimatesmartfee" command as a raw request,
|
||||
// since it isn't supported by btcd but is available in bitcoind.
|
||||
target, err := json.Marshal(uint64(confTarget))
|
||||
@@ -478,26 +433,26 @@ func (b *BitcoindFeeEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight,
|
||||
|
||||
// Finally, we'll enforce our fee floor.
|
||||
if satPerKw < b.minFeePerKW {
|
||||
walletLog.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,
|
||||
b.minFeePerKW)
|
||||
|
||||
satPerKw = b.minFeePerKW
|
||||
}
|
||||
|
||||
walletLog.Debugf("Returning %v sat/kw for conf target of %v",
|
||||
log.Debugf("Returning %v sat/kw for conf target of %v",
|
||||
int64(satPerKw), confTarget)
|
||||
|
||||
return satPerKw, nil
|
||||
}
|
||||
|
||||
// A compile-time assertion to ensure that BitcoindFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*BitcoindFeeEstimator)(nil)
|
||||
// A compile-time assertion to ensure that BitcoindEstimator implements the
|
||||
// Estimator interface.
|
||||
var _ Estimator = (*BitcoindEstimator)(nil)
|
||||
|
||||
// WebAPIFeeSource is an interface allows the WebAPIFeeEstimator to query an
|
||||
// WebAPIFeeSource is an interface allows the WebAPIEstimator to query an
|
||||
// arbitrary HTTP-based fee estimator. Each new set/network will gain an
|
||||
// implementation of this interface in order to allow the WebAPIFeeEstimator to
|
||||
// implementation of this interface in order to allow the WebAPIEstimator to
|
||||
// be fully generic in its logic.
|
||||
type WebAPIFeeSource interface {
|
||||
// GenQueryURL generates the full query URL. The value returned by this
|
||||
@@ -554,9 +509,9 @@ func (s SparseConfFeeSource) ParseResponse(r io.Reader) (map[uint32]uint32, erro
|
||||
// WebAPIFeeSource interface.
|
||||
var _ WebAPIFeeSource = (*SparseConfFeeSource)(nil)
|
||||
|
||||
// WebAPIFeeEstimator is an implementation of the FeeEstimator interface that
|
||||
// WebAPIEstimator is an implementation of the Estimator interface that
|
||||
// queries an HTTP-based fee estimation from an existing web API.
|
||||
type WebAPIFeeEstimator struct {
|
||||
type WebAPIEstimator struct {
|
||||
started sync.Once
|
||||
stopped sync.Once
|
||||
|
||||
@@ -581,12 +536,12 @@ type WebAPIFeeEstimator struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewWebAPIFeeEstimator creates a new WebAPIFeeEstimator from a given URL and a
|
||||
// NewWebAPIEstimator creates a new WebAPIEstimator from a given URL and a
|
||||
// fallback default fee. The fees are updated whenever a new block is mined.
|
||||
func NewWebAPIFeeEstimator(
|
||||
api WebAPIFeeSource, defaultFee SatPerKWeight) *WebAPIFeeEstimator {
|
||||
func NewWebAPIEstimator(
|
||||
api WebAPIFeeSource, defaultFee SatPerKWeight) *WebAPIEstimator {
|
||||
|
||||
return &WebAPIFeeEstimator{
|
||||
return &WebAPIEstimator{
|
||||
apiSource: api,
|
||||
feeByBlockTarget: make(map[uint32]uint32),
|
||||
defaultFeePerKw: defaultFee,
|
||||
@@ -597,8 +552,8 @@ func NewWebAPIFeeEstimator(
|
||||
// EstimateFeePerKW takes in a target for the number of blocks until an initial
|
||||
// confirmation and returns the estimated fee expressed in sat/kw.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (w *WebAPIFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight, error) {
|
||||
if numBlocks > maxBlockTarget {
|
||||
numBlocks = maxBlockTarget
|
||||
} else if numBlocks < minBlockTarget {
|
||||
@@ -618,20 +573,20 @@ func (w *WebAPIFeeEstimator) EstimateFeePerKW(numBlocks uint32) (SatPerKWeight,
|
||||
satPerKw = FeePerKwFloor
|
||||
}
|
||||
|
||||
walletLog.Debugf("Web API returning %v sat/kw for conf target of %v",
|
||||
log.Debugf("Web API returning %v sat/kw for conf target of %v",
|
||||
int64(satPerKw), numBlocks)
|
||||
|
||||
return satPerKw, nil
|
||||
}
|
||||
|
||||
// Start signals the FeeEstimator to start any processes or goroutines it needs
|
||||
// Start signals the Estimator to start any processes or goroutines it needs
|
||||
// to perform its duty.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (w *WebAPIFeeEstimator) Start() error {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (w *WebAPIEstimator) Start() error {
|
||||
var err error
|
||||
w.started.Do(func() {
|
||||
walletLog.Infof("Starting web API fee estimator")
|
||||
log.Infof("Starting web API fee estimator")
|
||||
|
||||
w.updateFeeTicker = time.NewTicker(w.randomFeeUpdateTimeout())
|
||||
w.updateFeeEstimates()
|
||||
@@ -646,10 +601,10 @@ func (w *WebAPIFeeEstimator) Start() error {
|
||||
// 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 (w *WebAPIFeeEstimator) Stop() error {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (w *WebAPIEstimator) Stop() error {
|
||||
w.stopped.Do(func() {
|
||||
walletLog.Infof("Stopping web API fee estimator")
|
||||
log.Infof("Stopping web API fee estimator")
|
||||
|
||||
w.updateFeeTicker.Stop()
|
||||
|
||||
@@ -662,15 +617,15 @@ func (w *WebAPIFeeEstimator) Stop() error {
|
||||
// RelayFeePerKW returns the minimum fee rate required for transactions to be
|
||||
// relayed.
|
||||
//
|
||||
// NOTE: This method is part of the FeeEstimator interface.
|
||||
func (w *WebAPIFeeEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
// NOTE: This method is part of the Estimator interface.
|
||||
func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight {
|
||||
return FeePerKwFloor
|
||||
}
|
||||
|
||||
// randomFeeUpdateTimeout returns a random timeout between minFeeUpdateTimeout
|
||||
// and maxFeeUpdateTimeout that will be used to determine how often the Estimator
|
||||
// should retrieve fresh fees from its API.
|
||||
func (w *WebAPIFeeEstimator) randomFeeUpdateTimeout() time.Duration {
|
||||
func (w *WebAPIEstimator) randomFeeUpdateTimeout() time.Duration {
|
||||
lower := int64(minFeeUpdateTimeout)
|
||||
upper := int64(maxFeeUpdateTimeout)
|
||||
return time.Duration(prand.Int63n(upper-lower) + lower)
|
||||
@@ -679,7 +634,7 @@ func (w *WebAPIFeeEstimator) randomFeeUpdateTimeout() time.Duration {
|
||||
// getCachedFee takes in a target for the number of blocks until an initial
|
||||
// confirmation and returns an estimated fee (if one was returned by the API). If
|
||||
// the fee was not previously cached, we cache it here.
|
||||
func (w *WebAPIFeeEstimator) getCachedFee(numBlocks uint32) (uint32, error) {
|
||||
func (w *WebAPIEstimator) getCachedFee(numBlocks uint32) (uint32, error) {
|
||||
w.feesMtx.Lock()
|
||||
defer w.feesMtx.Unlock()
|
||||
|
||||
@@ -704,7 +659,7 @@ func (w *WebAPIFeeEstimator) getCachedFee(numBlocks uint32) (uint32, error) {
|
||||
}
|
||||
|
||||
// updateFeeEstimates re-queries the API for fresh fees and caches them.
|
||||
func (w *WebAPIFeeEstimator) updateFeeEstimates() {
|
||||
func (w *WebAPIEstimator) updateFeeEstimates() {
|
||||
// Rather than use the default http.Client, we'll make a custom one
|
||||
// which will allow us to control how long we'll wait to read the
|
||||
// response from the service. This way, if the service is down or
|
||||
@@ -725,7 +680,7 @@ func (w *WebAPIFeeEstimator) updateFeeEstimates() {
|
||||
targetURL := w.apiSource.GenQueryURL()
|
||||
resp, err := netClient.Get(targetURL)
|
||||
if err != nil {
|
||||
walletLog.Errorf("unable to query web api for fee response: %v",
|
||||
log.Errorf("unable to query web api for fee response: %v",
|
||||
err)
|
||||
return
|
||||
}
|
||||
@@ -735,7 +690,7 @@ func (w *WebAPIFeeEstimator) updateFeeEstimates() {
|
||||
// to parse out the body to obtain our final result.
|
||||
feesByBlockTarget, err := w.apiSource.ParseResponse(resp.Body)
|
||||
if err != nil {
|
||||
walletLog.Errorf("unable to query web api for fee response: %v",
|
||||
log.Errorf("unable to query web api for fee response: %v",
|
||||
err)
|
||||
return
|
||||
}
|
||||
@@ -746,7 +701,7 @@ func (w *WebAPIFeeEstimator) updateFeeEstimates() {
|
||||
}
|
||||
|
||||
// feeUpdateManager updates the fee estimates whenever a new block comes in.
|
||||
func (w *WebAPIFeeEstimator) feeUpdateManager() {
|
||||
func (w *WebAPIEstimator) feeUpdateManager() {
|
||||
defer w.wg.Done()
|
||||
|
||||
for {
|
||||
@@ -759,6 +714,6 @@ func (w *WebAPIFeeEstimator) feeUpdateManager() {
|
||||
}
|
||||
}
|
||||
|
||||
// A compile-time assertion to ensure that WebAPIFeeEstimator implements the
|
||||
// FeeEstimator interface.
|
||||
var _ FeeEstimator = (*WebAPIFeeEstimator)(nil)
|
||||
// A compile-time assertion to ensure that WebAPIEstimator implements the
|
||||
// Estimator interface.
|
||||
var _ Estimator = (*WebAPIEstimator)(nil)
|
||||
@@ -1,4 +1,4 @@
|
||||
package lnwallet_test
|
||||
package chainfee
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,8 +9,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
type mockSparseConfFeeSource struct {
|
||||
@@ -38,9 +36,9 @@ func TestFeeRateTypes(t *testing.T) {
|
||||
const weight = vsize * 4
|
||||
|
||||
// Test the conversion from sat/kw to sat/kb.
|
||||
for feePerKw := lnwallet.SatPerKWeight(250); feePerKw < 10000; feePerKw += 50 {
|
||||
for feePerKw := SatPerKWeight(250); feePerKw < 10000; feePerKw += 50 {
|
||||
feePerKB := feePerKw.FeePerKVByte()
|
||||
if feePerKB != lnwallet.SatPerKVByte(feePerKw*4) {
|
||||
if feePerKB != SatPerKVByte(feePerKw*4) {
|
||||
t.Fatalf("expected %d sat/kb, got %d sat/kb when "+
|
||||
"converting from %d sat/kw", feePerKw*4,
|
||||
feePerKB, feePerKw)
|
||||
@@ -62,9 +60,9 @@ func TestFeeRateTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test the conversion from sat/kb to sat/kw.
|
||||
for feePerKB := lnwallet.SatPerKVByte(1000); feePerKB < 40000; feePerKB += 1000 {
|
||||
for feePerKB := SatPerKVByte(1000); feePerKB < 40000; feePerKB += 1000 {
|
||||
feePerKw := feePerKB.FeePerKWeight()
|
||||
if feePerKw != lnwallet.SatPerKWeight(feePerKB/4) {
|
||||
if feePerKw != SatPerKWeight(feePerKB/4) {
|
||||
t.Fatalf("expected %d sat/kw, got %d sat/kw when "+
|
||||
"converting from %d sat/kb", feePerKB/4,
|
||||
feePerKw, feePerKB)
|
||||
@@ -91,9 +89,9 @@ func TestFeeRateTypes(t *testing.T) {
|
||||
func TestStaticFeeEstimator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const feePerKw = lnwallet.FeePerKwFloor
|
||||
const feePerKw = FeePerKwFloor
|
||||
|
||||
feeEstimator := lnwallet.NewStaticFeeEstimator(feePerKw, 0)
|
||||
feeEstimator := NewStaticEstimator(feePerKw, 0)
|
||||
if err := feeEstimator.Start(); err != nil {
|
||||
t.Fatalf("unable to start fee estimator: %v", err)
|
||||
}
|
||||
@@ -116,7 +114,7 @@ func TestSparseConfFeeSource(t *testing.T) {
|
||||
|
||||
// Test that GenQueryURL returns the URL as is.
|
||||
url := "test"
|
||||
feeSource := lnwallet.SparseConfFeeSource{URL: url}
|
||||
feeSource := SparseConfFeeSource{URL: url}
|
||||
queryURL := feeSource.GenQueryURL()
|
||||
if queryURL != url {
|
||||
t.Fatalf("expected query URL of %v, got %v", url, queryURL)
|
||||
@@ -166,7 +164,7 @@ func TestSparseConfFeeSource(t *testing.T) {
|
||||
func TestWebAPIFeeEstimator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
feeFloor := uint32(lnwallet.FeePerKwFloor.FeePerKVByte())
|
||||
feeFloor := uint32(FeePerKwFloor.FeePerKVByte())
|
||||
testCases := []struct {
|
||||
name string
|
||||
target uint32
|
||||
@@ -194,7 +192,7 @@ func TestWebAPIFeeEstimator(t *testing.T) {
|
||||
fees: testFees,
|
||||
}
|
||||
|
||||
estimator := lnwallet.NewWebAPIFeeEstimator(feeSource, 10)
|
||||
estimator := NewWebAPIEstimator(feeSource, 10)
|
||||
|
||||
// Test that requesting a fee when no fees have been cached fails.
|
||||
_, err := estimator.EstimateFeePerKW(5)
|
||||
@@ -210,6 +208,7 @@ func TestWebAPIFeeEstimator(t *testing.T) {
|
||||
defer estimator.Stop()
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
est, err := estimator.EstimateFeePerKW(tc.target)
|
||||
if tc.err != "" {
|
||||
@@ -220,7 +219,7 @@ func TestWebAPIFeeEstimator(t *testing.T) {
|
||||
"fail, instead got: %v", err)
|
||||
}
|
||||
} else {
|
||||
exp := lnwallet.SatPerKVByte(tc.est).FeePerKWeight()
|
||||
exp := SatPerKVByte(tc.est).FeePerKWeight()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to estimate fee for "+
|
||||
"%v block target, got: %v",
|
||||
@@ -0,0 +1,29 @@
|
||||
package chainfee
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This means the
|
||||
// package will not perform any logging by default until the caller requests
|
||||
// it.
|
||||
var log btclog.Logger
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
UseLogger(build.NewSubLogger("CFEE", nil))
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled by
|
||||
// default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
UseLogger(btclog.Disabled)
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info. This
|
||||
// should be used in preference to SetLogWriter if the caller is also using
|
||||
// btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package chainfee
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// FeePerKwFloor is the lowest fee rate in sat/kw that we should use for
|
||||
// determining transaction fees.
|
||||
FeePerKwFloor SatPerKWeight = 253
|
||||
)
|
||||
|
||||
// SatPerKVByte represents a fee rate in sat/kb.
|
||||
type SatPerKVByte btcutil.Amount
|
||||
|
||||
// FeeForVSize calculates the fee resulting from this fee rate and the given
|
||||
// vsize in vbytes.
|
||||
func (s SatPerKVByte) FeeForVSize(vbytes int64) btcutil.Amount {
|
||||
return btcutil.Amount(s) * btcutil.Amount(vbytes) / 1000
|
||||
}
|
||||
|
||||
// FeePerKWeight converts the current fee rate from sat/kb to sat/kw.
|
||||
func (s SatPerKVByte) FeePerKWeight() SatPerKWeight {
|
||||
return SatPerKWeight(s / blockchain.WitnessScaleFactor)
|
||||
}
|
||||
|
||||
// String returns a human-readable string of the fee rate.
|
||||
func (s SatPerKVByte) String() string {
|
||||
return fmt.Sprintf("%v sat/kb", int64(s))
|
||||
}
|
||||
|
||||
// SatPerKWeight represents a fee rate in sat/kw.
|
||||
type SatPerKWeight btcutil.Amount
|
||||
|
||||
// FeeForWeight calculates the fee resulting from this fee rate and the given
|
||||
// weight in weight units (wu).
|
||||
func (s SatPerKWeight) FeeForWeight(wu int64) btcutil.Amount {
|
||||
// The resulting fee is rounded down, as specified in BOLT#03.
|
||||
return btcutil.Amount(s) * btcutil.Amount(wu) / 1000
|
||||
}
|
||||
|
||||
// FeePerKVByte converts the current fee rate from sat/kw to sat/kb.
|
||||
func (s SatPerKWeight) FeePerKVByte() SatPerKVByte {
|
||||
return SatPerKVByte(s * blockchain.WitnessScaleFactor)
|
||||
}
|
||||
|
||||
// String returns a human-readable string of the fee rate.
|
||||
func (s SatPerKWeight) String() string {
|
||||
return fmt.Sprintf("%v sat/kw", int64(s))
|
||||
}
|
||||
+39
-33
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@@ -512,7 +513,7 @@ type commitment struct {
|
||||
|
||||
// feePerKw is the fee per kw used to calculate this commitment
|
||||
// transaction's fee.
|
||||
feePerKw SatPerKWeight
|
||||
feePerKw chainfee.SatPerKWeight
|
||||
|
||||
// dustLimit is the limit on the commitment transaction such that no
|
||||
// output values should be below this amount.
|
||||
@@ -759,7 +760,7 @@ func (c *commitment) toDiskCommit(ourCommit bool) *channeldb.ChannelCommitment {
|
||||
// commitment struct and updateLog. This function is used when we need to
|
||||
// restore commitment state written do disk back into memory once we need to
|
||||
// restart a channel session.
|
||||
func (lc *LightningChannel) diskHtlcToPayDesc(feeRate SatPerKWeight,
|
||||
func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
||||
commitHeight uint64, htlc *channeldb.HTLC, localCommitKeys,
|
||||
remoteCommitKeys *CommitmentKeyRing) (PaymentDescriptor, error) {
|
||||
|
||||
@@ -824,7 +825,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate SatPerKWeight,
|
||||
// these payment descriptors can be re-inserted into the in-memory updateLog
|
||||
// for each side.
|
||||
func (lc *LightningChannel) extractPayDescs(commitHeight uint64,
|
||||
feeRate SatPerKWeight, htlcs []channeldb.HTLC, localCommitKeys,
|
||||
feeRate chainfee.SatPerKWeight, htlcs []channeldb.HTLC, localCommitKeys,
|
||||
remoteCommitKeys *CommitmentKeyRing) ([]PaymentDescriptor, []PaymentDescriptor, error) {
|
||||
|
||||
var (
|
||||
@@ -893,7 +894,8 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool,
|
||||
// HTLC"s into PaymentDescriptor's so we can re-insert them into our
|
||||
// update log.
|
||||
incomingHtlcs, outgoingHtlcs, err := lc.extractPayDescs(
|
||||
diskCommit.CommitHeight, SatPerKWeight(diskCommit.FeePerKw),
|
||||
diskCommit.CommitHeight,
|
||||
chainfee.SatPerKWeight(diskCommit.FeePerKw),
|
||||
diskCommit.Htlcs, localCommitKeys, remoteCommitKeys,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -914,7 +916,7 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool,
|
||||
txn: diskCommit.CommitTx,
|
||||
sig: diskCommit.CommitSig,
|
||||
fee: diskCommit.CommitFee,
|
||||
feePerKw: SatPerKWeight(diskCommit.FeePerKw),
|
||||
feePerKw: chainfee.SatPerKWeight(diskCommit.FeePerKw),
|
||||
incomingHTLCs: incomingHtlcs,
|
||||
outgoingHTLCs: outgoingHtlcs,
|
||||
}
|
||||
@@ -1508,7 +1510,7 @@ func (lc *LightningChannel) ResetState() {
|
||||
// if nothing happened.
|
||||
func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
||||
remoteUpdateLog *updateLog, commitHeight uint64,
|
||||
feeRate SatPerKWeight, remoteCommitKeys *CommitmentKeyRing,
|
||||
feeRate chainfee.SatPerKWeight, remoteCommitKeys *CommitmentKeyRing,
|
||||
remoteDustLimit btcutil.Amount) (*PaymentDescriptor, error) {
|
||||
|
||||
// Depending on the type of update message we'll map that to a distinct
|
||||
@@ -1825,7 +1827,8 @@ func (lc *LightningChannel) restoreStateLogs(
|
||||
for _, logUpdate := range pendingRemoteCommitDiff.LogUpdates {
|
||||
payDesc, err := lc.logUpdateToPayDesc(
|
||||
&logUpdate, lc.remoteUpdateLog, pendingHeight,
|
||||
SatPerKWeight(pendingCommit.FeePerKw), pendingRemoteKeys,
|
||||
chainfee.SatPerKWeight(pendingCommit.FeePerKw),
|
||||
pendingRemoteKeys,
|
||||
lc.channelState.RemoteChanCfg.DustLimit,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -2108,7 +2111,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
||||
// an output on the commitment transaction.
|
||||
if htlcIsDust(
|
||||
htlc.Incoming, false,
|
||||
SatPerKWeight(revokedSnapshot.FeePerKw),
|
||||
chainfee.SatPerKWeight(revokedSnapshot.FeePerKw),
|
||||
htlc.Amt.ToSatoshis(), chanState.RemoteChanCfg.DustLimit,
|
||||
) {
|
||||
continue
|
||||
@@ -2197,13 +2200,13 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
||||
|
||||
// htlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
|
||||
// transaction based on the current fee rate.
|
||||
func htlcTimeoutFee(feePerKw SatPerKWeight) btcutil.Amount {
|
||||
func htlcTimeoutFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
||||
return feePerKw.FeeForWeight(input.HtlcTimeoutWeight)
|
||||
}
|
||||
|
||||
// htlcSuccessFee returns the fee in satoshis required for an HTLC success
|
||||
// transaction based on the current fee rate.
|
||||
func htlcSuccessFee(feePerKw SatPerKWeight) btcutil.Amount {
|
||||
func htlcSuccessFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
||||
return feePerKw.FeeForWeight(input.HtlcSuccessWeight)
|
||||
}
|
||||
|
||||
@@ -2213,7 +2216,7 @@ func htlcSuccessFee(feePerKw SatPerKWeight) btcutil.Amount {
|
||||
// require as we currently used second-level HTLC transactions as off-chain
|
||||
// covenants. Depending on the two bits, we'll either be using a timeout or
|
||||
// success transaction which have different weights.
|
||||
func htlcIsDust(incoming, ourCommit bool, feePerKw SatPerKWeight,
|
||||
func htlcIsDust(incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight,
|
||||
htlcAmt, dustLimit btcutil.Amount) bool {
|
||||
|
||||
// First we'll determine the fee required for this HTLC based on if this is
|
||||
@@ -2254,7 +2257,7 @@ func htlcIsDust(incoming, ourCommit bool, feePerKw SatPerKWeight,
|
||||
type htlcView struct {
|
||||
ourUpdates []*PaymentDescriptor
|
||||
theirUpdates []*PaymentDescriptor
|
||||
feePerKw SatPerKWeight
|
||||
feePerKw chainfee.SatPerKWeight
|
||||
}
|
||||
|
||||
// fetchHTLCView returns all the candidate HTLC updates which should be
|
||||
@@ -2785,7 +2788,7 @@ func processFeeUpdate(feeUpdate *PaymentDescriptor, nextHeight uint64,
|
||||
|
||||
// If the update wasn't already locked in, update the current fee rate
|
||||
// to reflect this update.
|
||||
view.feePerKw = SatPerKWeight(feeUpdate.Amount.ToSatoshis())
|
||||
view.feePerKw = chainfee.SatPerKWeight(feeUpdate.Amount.ToSatoshis())
|
||||
|
||||
if mutateState {
|
||||
*addHeight = nextHeight
|
||||
@@ -3130,9 +3133,9 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
||||
|
||||
// Ensure that the fee being applied is enough to be relayed across the
|
||||
// network in a reasonable time frame.
|
||||
if feePerKw < FeePerKwFloor {
|
||||
if feePerKw < chainfee.FeePerKwFloor {
|
||||
return fmt.Errorf("commitment fee per kw %v below fee floor %v",
|
||||
feePerKw, FeePerKwFloor)
|
||||
feePerKw, chainfee.FeePerKwFloor)
|
||||
}
|
||||
|
||||
// If the added HTLCs will decrease the balance, make sure they won't
|
||||
@@ -5048,7 +5051,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
|
||||
// Next, we'll obtain HTLC resolutions for all the outgoing HTLC's we
|
||||
// had on their commitment transaction.
|
||||
htlcResolutions, err := extractHtlcResolutions(
|
||||
SatPerKWeight(remoteCommit.FeePerKw), false, signer,
|
||||
chainfee.SatPerKWeight(remoteCommit.FeePerKw), false, signer,
|
||||
remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
||||
&chanState.RemoteChanCfg, *commitSpend.SpenderTxHash,
|
||||
)
|
||||
@@ -5245,10 +5248,11 @@ type HtlcResolutions struct {
|
||||
// newOutgoingHtlcResolution generates a new HTLC resolution capable of
|
||||
// allowing the caller to sweep an outgoing HTLC present on either their, or
|
||||
// the remote party's commitment transaction.
|
||||
func newOutgoingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig,
|
||||
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32, localCommit bool,
|
||||
) (*OutgoingHtlcResolution, error) {
|
||||
func newOutgoingHtlcResolution(signer input.Signer,
|
||||
localChanCfg *channeldb.ChannelConfig, commitHash chainhash.Hash,
|
||||
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||
feePerKw chainfee.SatPerKWeight, csvDelay uint32,
|
||||
localCommit bool) (*OutgoingHtlcResolution, error) {
|
||||
|
||||
op := wire.OutPoint{
|
||||
Hash: commitHash,
|
||||
@@ -5387,7 +5391,7 @@ func newOutgoingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan
|
||||
// TODO(roasbeef) consolidate code with above func
|
||||
func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig,
|
||||
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32,
|
||||
feePerKw chainfee.SatPerKWeight, csvDelay uint32,
|
||||
localCommit bool) (*IncomingHtlcResolution, error) {
|
||||
|
||||
op := wire.OutPoint{
|
||||
@@ -5541,7 +5545,7 @@ func (r *OutgoingHtlcResolution) HtlcPoint() wire.OutPoint {
|
||||
// extractHtlcResolutions creates a series of outgoing HTLC resolutions, and
|
||||
// the local key used when generating the HTLC scrips. This function is to be
|
||||
// used in two cases: force close, or a unilateral close.
|
||||
func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
|
||||
func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
|
||||
signer input.Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
||||
commitHash chainhash.Hash) (*HtlcResolutions, error) {
|
||||
@@ -5572,7 +5576,7 @@ func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
|
||||
// as we can satisfy the contract.
|
||||
ihr, err := newIncomingHtlcResolution(
|
||||
signer, localChanCfg, commitHash, &htlc, keyRing,
|
||||
feePerKw, dustLimit, uint32(csvDelay), ourCommit,
|
||||
feePerKw, uint32(csvDelay), ourCommit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -5584,7 +5588,7 @@ func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
|
||||
|
||||
ohr, err := newOutgoingHtlcResolution(
|
||||
signer, localChanCfg, commitHash, &htlc, keyRing,
|
||||
feePerKw, dustLimit, uint32(csvDelay), ourCommit,
|
||||
feePerKw, uint32(csvDelay), ourCommit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -5762,7 +5766,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
|
||||
// outgoing HTLC's that we'll need to claim as well.
|
||||
txHash := commitTx.TxHash()
|
||||
htlcResolutions, err := extractHtlcResolutions(
|
||||
SatPerKWeight(localCommit.FeePerKw), true, signer,
|
||||
chainfee.SatPerKWeight(localCommit.FeePerKw), true, signer,
|
||||
localCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
||||
&chanState.RemoteChanCfg, txHash,
|
||||
)
|
||||
@@ -5980,7 +5984,7 @@ func (lc *LightningChannel) StateSnapshot() *channeldb.ChannelSnapshot {
|
||||
// validateFeeRate ensures that if the passed fee is applied to the channel,
|
||||
// and a new commitment is created (which evaluates this fee), then the
|
||||
// initiator of the channel does not dip below their reserve.
|
||||
func (lc *LightningChannel) validateFeeRate(feePerKw SatPerKWeight) error {
|
||||
func (lc *LightningChannel) validateFeeRate(feePerKw chainfee.SatPerKWeight) error {
|
||||
// We'll ensure that we can accommodate this new fee change, yet still
|
||||
// be above our reserve balance. Otherwise, we'll reject the fee
|
||||
// update.
|
||||
@@ -6028,7 +6032,7 @@ func (lc *LightningChannel) validateFeeRate(feePerKw SatPerKWeight) error {
|
||||
// UpdateFee initiates a fee update for this channel. Must only be called by
|
||||
// the channel initiator, and must be called before sending update_fee to
|
||||
// the remote.
|
||||
func (lc *LightningChannel) UpdateFee(feePerKw SatPerKWeight) error {
|
||||
func (lc *LightningChannel) UpdateFee(feePerKw chainfee.SatPerKWeight) error {
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
|
||||
@@ -6056,7 +6060,7 @@ func (lc *LightningChannel) UpdateFee(feePerKw SatPerKWeight) error {
|
||||
|
||||
// ReceiveUpdateFee handles an updated fee sent from remote. This method will
|
||||
// return an error if called as channel initiator.
|
||||
func (lc *LightningChannel) ReceiveUpdateFee(feePerKw SatPerKWeight) error {
|
||||
func (lc *LightningChannel) ReceiveUpdateFee(feePerKw chainfee.SatPerKWeight) error {
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
|
||||
@@ -6212,7 +6216,7 @@ func CreateCooperativeCloseTx(fundingTxIn wire.TxIn,
|
||||
|
||||
// CalcFee returns the commitment fee to use for the given
|
||||
// fee rate (fee-per-kw).
|
||||
func (lc *LightningChannel) CalcFee(feeRate SatPerKWeight) btcutil.Amount {
|
||||
func (lc *LightningChannel) CalcFee(feeRate chainfee.SatPerKWeight) btcutil.Amount {
|
||||
return feeRate.FeeForWeight(input.CommitWeight)
|
||||
}
|
||||
|
||||
@@ -6222,7 +6226,7 @@ func (lc *LightningChannel) CalcFee(feeRate SatPerKWeight) btcutil.Amount {
|
||||
//
|
||||
// NOTE: This should only be used for channels in which the local commitment is
|
||||
// the initiator.
|
||||
func (lc *LightningChannel) MaxFeeRate(maxAllocation float64) SatPerKWeight {
|
||||
func (lc *LightningChannel) MaxFeeRate(maxAllocation float64) chainfee.SatPerKWeight {
|
||||
lc.RLock()
|
||||
defer lc.RUnlock()
|
||||
|
||||
@@ -6236,7 +6240,9 @@ func (lc *LightningChannel) MaxFeeRate(maxAllocation float64) SatPerKWeight {
|
||||
|
||||
// Ensure the fee rate doesn't dip below the fee floor.
|
||||
maxFeeRate := maxFee / (float64(weight) / 1000)
|
||||
return SatPerKWeight(math.Max(maxFeeRate, float64(FeePerKwFloor)))
|
||||
return chainfee.SatPerKWeight(
|
||||
math.Max(maxFeeRate, float64(chainfee.FeePerKwFloor)),
|
||||
)
|
||||
}
|
||||
|
||||
// RemoteNextRevocation returns the channelState's RemoteNextRevocation.
|
||||
@@ -6259,11 +6265,11 @@ func (lc *LightningChannel) IsInitiator() bool {
|
||||
|
||||
// CommitFeeRate returns the current fee rate of the commitment transaction in
|
||||
// units of sat-per-kw.
|
||||
func (lc *LightningChannel) CommitFeeRate() SatPerKWeight {
|
||||
func (lc *LightningChannel) CommitFeeRate() chainfee.SatPerKWeight {
|
||||
lc.RLock()
|
||||
defer lc.RUnlock()
|
||||
|
||||
return SatPerKWeight(lc.channelState.LocalCommitment.FeePerKw)
|
||||
return chainfee.SatPerKWeight(lc.channelState.LocalCommitment.FeePerKw)
|
||||
}
|
||||
|
||||
// IsPending returns true if the channel's funding transaction has been fully
|
||||
|
||||
+105
-47
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@@ -456,8 +457,12 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
||||
aliceDeliveryScript := bobsPrivKey[:]
|
||||
bobDeliveryScript := testHdSeed[:]
|
||||
|
||||
aliceFeeRate := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||
bobFeeRate := SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw)
|
||||
aliceFeeRate := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
bobFeeRate := chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
|
||||
// We'll store with both Alice and Bob creating a new close proposal
|
||||
// with the same fee.
|
||||
@@ -596,7 +601,9 @@ func TestForceClose(t *testing.T) {
|
||||
// Factoring in the fee rate, Alice's amount should properly reflect
|
||||
// that we've added two additional HTLC to the commitment transaction.
|
||||
totalCommitWeight := input.CommitWeight + (input.HtlcWeight * 2)
|
||||
feePerKw := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||
feePerKw := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
commitFee := feePerKw.FeeForWeight(totalCommitWeight)
|
||||
expectedAmount := (aliceChannel.Capacity / 2) - htlcAmount.ToSatoshis() - commitFee
|
||||
if aliceCommitResolution.SelfOutputSignDesc.Output.Value != int64(expectedAmount) {
|
||||
@@ -1004,7 +1011,10 @@ func TestHTLCDustLimit(t *testing.T) {
|
||||
// The amount of the HTLC should be above Alice's dust limit and below
|
||||
// Bob's dust limit.
|
||||
htlcSat := (btcutil.Amount(500) + htlcTimeoutFee(
|
||||
SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)))
|
||||
chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
),
|
||||
))
|
||||
htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat)
|
||||
|
||||
htlc, preimage := createHTLC(0, htlcAmount)
|
||||
@@ -1102,7 +1112,7 @@ func TestHTLCSigNumber(t *testing.T) {
|
||||
}
|
||||
|
||||
// Calculate two values that will be below and above Bob's dust limit.
|
||||
estimator := NewStaticFeeEstimator(6000, 0)
|
||||
estimator := chainfee.NewStaticEstimator(6000, 0)
|
||||
feePerKw, err := estimator.EstimateFeePerKW(1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get fee: %v", err)
|
||||
@@ -1268,7 +1278,9 @@ func TestChannelBalanceDustLimit(t *testing.T) {
|
||||
aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis()
|
||||
htlcSat := aliceBalance - defaultFee
|
||||
htlcSat += htlcSuccessFee(
|
||||
SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw),
|
||||
chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
),
|
||||
)
|
||||
|
||||
htlcAmount := lnwire.NewMSatFromSatoshis(htlcSat)
|
||||
@@ -1366,7 +1378,7 @@ func TestStateUpdatePersistence(t *testing.T) {
|
||||
}
|
||||
|
||||
// Also add a fee update to the update logs.
|
||||
fee := SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
if err := aliceChannel.UpdateFee(fee); err != nil {
|
||||
t.Fatalf("unable to send fee update")
|
||||
}
|
||||
@@ -1779,8 +1791,12 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
||||
}
|
||||
defer cleanUp()
|
||||
|
||||
aliceFeeRate := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||
bobFeeRate := SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw)
|
||||
aliceFeeRate := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
bobFeeRate := chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
|
||||
setDustLimit := func(dustVal btcutil.Amount) {
|
||||
aliceChannel.channelState.LocalChanCfg.DustLimit = dustVal
|
||||
@@ -1946,7 +1962,7 @@ func TestUpdateFeeAdjustments(t *testing.T) {
|
||||
|
||||
// We'll first try to increase the fee rate 5x, this should be able to
|
||||
// be committed without any issue.
|
||||
newFee := SatPerKWeight(baseFeeRate * 5)
|
||||
newFee := chainfee.SatPerKWeight(baseFeeRate * 5)
|
||||
|
||||
if err := aliceChannel.UpdateFee(newFee); err != nil {
|
||||
t.Fatalf("unable to alice update fee: %v", err)
|
||||
@@ -1964,7 +1980,7 @@ func TestUpdateFeeAdjustments(t *testing.T) {
|
||||
// We'll now attempt to increase the fee rate 1,000,000x of the base
|
||||
// fee. This should result in an error as Alice won't be able to pay
|
||||
// this new fee rate.
|
||||
newFee = SatPerKWeight(baseFeeRate * 1000000)
|
||||
newFee = chainfee.SatPerKWeight(baseFeeRate * 1000000)
|
||||
if err := aliceChannel.UpdateFee(newFee); err == nil {
|
||||
t.Fatalf("alice should reject the fee rate")
|
||||
}
|
||||
@@ -1972,7 +1988,7 @@ func TestUpdateFeeAdjustments(t *testing.T) {
|
||||
// Finally, we'll attempt to adjust the fee down and use a fee which is
|
||||
// smaller than the initial base fee rate. The fee application and
|
||||
// state transition should proceed without issue.
|
||||
newFee = SatPerKWeight(baseFeeRate / 10)
|
||||
newFee = chainfee.SatPerKWeight(baseFeeRate / 10)
|
||||
if err := aliceChannel.UpdateFee(newFee); err != nil {
|
||||
t.Fatalf("unable to alice update fee: %v", err)
|
||||
}
|
||||
@@ -2048,7 +2064,7 @@ func TestUpdateFeeConcurrentSig(t *testing.T) {
|
||||
}
|
||||
|
||||
// Simulate Alice sending update fee message to bob.
|
||||
fee := SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
if err := aliceChannel.UpdateFee(fee); err != nil {
|
||||
t.Fatalf("unable to send fee update")
|
||||
}
|
||||
@@ -2084,7 +2100,7 @@ func TestUpdateFeeConcurrentSig(t *testing.T) {
|
||||
t.Fatalf("bob unable to process alice's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
t.Fatalf("bob's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2095,7 +2111,7 @@ func TestUpdateFeeConcurrentSig(t *testing.T) {
|
||||
t.Fatalf("unable to generate bob revocation: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
}
|
||||
@@ -2134,7 +2150,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
}
|
||||
|
||||
// Simulate Alice sending update fee message to bob.
|
||||
fee := SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
aliceChannel.UpdateFee(fee)
|
||||
bobChannel.ReceiveUpdateFee(fee)
|
||||
|
||||
@@ -2154,7 +2170,9 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
t.Fatalf("bob unable to process alice's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("bob's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2165,7 +2183,9 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
t.Fatalf("unable to generate bob revocation: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -2191,7 +2211,9 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
t.Fatalf("alice unable to process bob's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("alice's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2202,7 +2224,9 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
t.Fatalf("unable to revoke alice channel: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("alice's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -2248,7 +2272,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
}
|
||||
|
||||
// Simulate Alice sending update fee message to bob
|
||||
fee := SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
aliceChannel.UpdateFee(fee)
|
||||
bobChannel.ReceiveUpdateFee(fee)
|
||||
|
||||
@@ -2296,7 +2320,9 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
t.Fatalf("alice unable to process bob's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("bob's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2308,7 +2334,9 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
t.Fatalf("unable to revoke alice channel: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -2333,7 +2361,9 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
t.Fatalf("alice unable to process bob's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("alice's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2344,7 +2374,9 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
t.Fatalf("unable to generate bob revocation: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("Alice's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -2372,7 +2404,7 @@ func TestUpdateFeeReceiverSendsUpdate(t *testing.T) {
|
||||
|
||||
// Since Alice is the channel initiator, she should fail when receiving
|
||||
// fee update
|
||||
fee := SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
err = aliceChannel.ReceiveUpdateFee(fee)
|
||||
if err == nil {
|
||||
t.Fatalf("expected alice to fail receiving fee update")
|
||||
@@ -2400,9 +2432,9 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
defer cleanUp()
|
||||
|
||||
// Simulate Alice sending update fee message to bob.
|
||||
fee1 := SatPerKWeight(333)
|
||||
fee2 := SatPerKWeight(333)
|
||||
fee := SatPerKWeight(333)
|
||||
fee1 := chainfee.SatPerKWeight(333)
|
||||
fee2 := chainfee.SatPerKWeight(333)
|
||||
fee := chainfee.SatPerKWeight(333)
|
||||
aliceChannel.UpdateFee(fee1)
|
||||
aliceChannel.UpdateFee(fee2)
|
||||
aliceChannel.UpdateFee(fee)
|
||||
@@ -2427,15 +2459,17 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
t.Fatalf("bob unable to process alice's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("bob's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
// Alice sending more fee updates now should not mess up the old fee
|
||||
// they both committed to.
|
||||
fee3 := SatPerKWeight(444)
|
||||
fee4 := SatPerKWeight(555)
|
||||
fee5 := SatPerKWeight(666)
|
||||
fee3 := chainfee.SatPerKWeight(444)
|
||||
fee4 := chainfee.SatPerKWeight(555)
|
||||
fee5 := chainfee.SatPerKWeight(666)
|
||||
aliceChannel.UpdateFee(fee3)
|
||||
aliceChannel.UpdateFee(fee4)
|
||||
aliceChannel.UpdateFee(fee5)
|
||||
@@ -2450,7 +2484,9 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
t.Fatalf("unable to generate bob revocation: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -2475,7 +2511,9 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
t.Fatalf("alice unable to process bob's new commitment: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) == fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) == fee {
|
||||
t.Fatalf("alice's feePerKw was unexpectedly locked in")
|
||||
}
|
||||
|
||||
@@ -2486,7 +2524,9 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
t.Fatalf("unable to revoke alice channel: %v", err)
|
||||
}
|
||||
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != fee {
|
||||
t.Fatalf("alice's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -3869,7 +3909,9 @@ func TestFeeUpdateRejectInsaneFee(t *testing.T) {
|
||||
|
||||
// Next, we'll try to add a fee rate to Alice which is 1,000,000x her
|
||||
// starting fee rate.
|
||||
startingFeeRate := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||
startingFeeRate := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
newFeeRate := startingFeeRate * 1000000
|
||||
|
||||
// Both Alice and Bob should reject this new fee rate as it is far too
|
||||
@@ -3895,7 +3937,9 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
||||
|
||||
// First, we'll fetch the current fee rate present within the
|
||||
// commitment transactions.
|
||||
startingFeeRate := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||
startingFeeRate := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
|
||||
// Next, we'll start a commitment update, with Alice sending a new
|
||||
// update to double the fee rate of the commitment.
|
||||
@@ -4034,10 +4078,14 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
// Both parties should now have the latest fee rate locked-in.
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("alice's feePerKw was not locked in")
|
||||
}
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -4118,7 +4166,7 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
||||
|
||||
// First, we'll fetch the current fee rate present within the
|
||||
// commitment transactions.
|
||||
startingFeeRate := SatPerKWeight(
|
||||
startingFeeRate := chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
)
|
||||
newFeeRate := startingFeeRate
|
||||
@@ -4247,10 +4295,14 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
// Both parties should now have the latest fee rate locked-in.
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("alice's feePerKw was not locked in")
|
||||
}
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
|
||||
@@ -4272,10 +4324,14 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
||||
assertLogItems(0, numHTLCs+1)
|
||||
|
||||
// ...and the final fee rate locked in.
|
||||
if SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("alice's feePerKw was not locked in")
|
||||
}
|
||||
if SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != newFeeRate {
|
||||
if chainfee.SatPerKWeight(
|
||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||
) != newFeeRate {
|
||||
t.Fatalf("bob's feePerKw was not locked in")
|
||||
}
|
||||
}
|
||||
@@ -6624,7 +6680,9 @@ func TestChannelMaxFeeRate(t *testing.T) {
|
||||
}
|
||||
defer cleanUp()
|
||||
|
||||
assertMaxFeeRate := func(maxAlloc float64, expFeeRate SatPerKWeight) {
|
||||
assertMaxFeeRate := func(maxAlloc float64,
|
||||
expFeeRate chainfee.SatPerKWeight) {
|
||||
|
||||
maxFeeRate := aliceChannel.MaxFeeRate(maxAlloc)
|
||||
if maxFeeRate != expFeeRate {
|
||||
t.Fatalf("expected max fee rate of %v with max "+
|
||||
@@ -6636,5 +6694,5 @@ func TestChannelMaxFeeRate(t *testing.T) {
|
||||
assertMaxFeeRate(1.0, 690607734)
|
||||
assertMaxFeeRate(0.001, 690607)
|
||||
assertMaxFeeRate(0.000001, 690)
|
||||
assertMaxFeeRate(0.0000001, FeePerKwFloor)
|
||||
assertMaxFeeRate(0.0000001, chainfee.FeePerKwFloor)
|
||||
}
|
||||
+2
-1
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
// Config is a struct which houses configuration parameters which modify the
|
||||
@@ -42,7 +43,7 @@ type Config struct {
|
||||
|
||||
// FeeEstimator is the implementation that the wallet will use for the
|
||||
// calculation of on-chain transaction fees.
|
||||
FeeEstimator FeeEstimator
|
||||
FeeEstimator chainfee.Estimator
|
||||
|
||||
// ChainIO is an instance of the BlockChainIO interface. ChainIO is
|
||||
// used to lookup the existence of outputs within the UTXO set.
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/wallet/txauthor"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
// AddressType is an enum-like type which denotes the possible address types
|
||||
@@ -172,7 +173,7 @@ type WalletController interface {
|
||||
// This method also takes the target fee expressed in sat/kw that should
|
||||
// be used when crafting the transaction.
|
||||
SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate SatPerKWeight) (*wire.MsgTx, error)
|
||||
feeRate chainfee.SatPerKWeight) (*wire.MsgTx, error)
|
||||
|
||||
// CreateSimpleTx creates a Bitcoin transaction paying to the specified
|
||||
// outputs. The transaction is not broadcasted to the network. In the
|
||||
@@ -184,7 +185,7 @@ type WalletController interface {
|
||||
// NOTE: The dryRun argument can be set true to create a tx that
|
||||
// doesn't alter the database. A tx created with this set to true
|
||||
// SHOULD NOT be broadcasted.
|
||||
CreateSimpleTx(outputs []*wire.TxOut, feeRate SatPerKWeight,
|
||||
CreateSimpleTx(outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
|
||||
dryRun bool) (*txauthor.AuthoredTx, error)
|
||||
|
||||
// ListUnspentWitness returns all unspent outputs which are version 0
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@@ -166,7 +167,7 @@ func newPkScript(t *testing.T, w *lnwallet.LightningWallet,
|
||||
// parties to send on-chain funds to each other.
|
||||
func sendCoins(t *testing.T, miner *rpctest.Harness,
|
||||
sender, receiver *lnwallet.LightningWallet, output *wire.TxOut,
|
||||
feeRate lnwallet.SatPerKWeight) *wire.MsgTx {
|
||||
feeRate chainfee.SatPerKWeight) *wire.MsgTx { //nolint:unparam
|
||||
|
||||
t.Helper()
|
||||
|
||||
@@ -330,7 +331,7 @@ func createTestWallet(tempTestDir string, miningNode *rpctest.Harness,
|
||||
WalletController: wc,
|
||||
Signer: signer,
|
||||
ChainIO: bio,
|
||||
FeeEstimator: lnwallet.NewStaticFeeEstimator(2500, 0),
|
||||
FeeEstimator: chainfee.NewStaticEstimator(2500, 0),
|
||||
DefaultConstraints: channeldb.ChannelConstraints{
|
||||
DustLimit: 500,
|
||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) * 100,
|
||||
@@ -723,7 +724,7 @@ func testReservationInitiatorBalanceBelowDustCancel(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create amt: %v", err)
|
||||
}
|
||||
|
||||
feePerKw := lnwallet.SatPerKWeight(
|
||||
feePerKw := chainfee.SatPerKWeight(
|
||||
numBTC * numBTC * btcutil.SatoshiPerBitcoin,
|
||||
)
|
||||
req := &lnwallet.InitFundingReserveMsg{
|
||||
@@ -2151,7 +2152,7 @@ func testChangeOutputSpendConfirmation(r *rpctest.Harness,
|
||||
//
|
||||
// TODO(wilmer): replace this once SendOutputs easily supports sending
|
||||
// all funds in one transaction.
|
||||
txFeeRate := lnwallet.SatPerKWeight(2500)
|
||||
txFeeRate := chainfee.SatPerKWeight(2500)
|
||||
txFee := btcutil.Amount(14380)
|
||||
output := &wire.TxOut{
|
||||
Value: int64(aliceBalance - txFee),
|
||||
@@ -2247,7 +2248,7 @@ func testLastUnusedAddr(miner *rpctest.Harness,
|
||||
if err != nil {
|
||||
t.Fatalf("unable to convert addr to script: %v", err)
|
||||
}
|
||||
feeRate := lnwallet.SatPerKWeight(2500)
|
||||
feeRate := chainfee.SatPerKWeight(2500)
|
||||
output := &wire.TxOut{
|
||||
Value: 1000000,
|
||||
PkScript: addrScript,
|
||||
@@ -2281,7 +2282,7 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
||||
// The test cases we will run through for all backends.
|
||||
testCases := []struct {
|
||||
outVals []int64
|
||||
feeRate lnwallet.SatPerKWeight
|
||||
feeRate chainfee.SatPerKWeight
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/btcsuite/btcwallet/wtxmgr"
|
||||
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
// walletLog is a logger that is initialized with no output filters. This
|
||||
@@ -34,6 +35,7 @@ func UseLogger(logger btclog.Logger) {
|
||||
btcwallet.UseLogger(logger)
|
||||
wtxmgr.UseLogger(logger)
|
||||
chain.UseLogger(logger)
|
||||
chainfee.UseLogger(logger)
|
||||
}
|
||||
|
||||
// logClosure is used to provide a closure over expensive logging operations
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@@ -128,7 +129,7 @@ type ChannelReservation struct {
|
||||
// creation of all channel reservations should be carried out via the
|
||||
// lnwallet.InitChannelReservation interface.
|
||||
func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
||||
commitFeePerKw SatPerKWeight, wallet *LightningWallet,
|
||||
commitFeePerKw chainfee.SatPerKWeight, wallet *LightningWallet,
|
||||
id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash,
|
||||
flags lnwire.FundingFlag,
|
||||
tweaklessCommit bool) (*ChannelReservation, error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/shachain"
|
||||
)
|
||||
@@ -233,7 +234,7 @@ func CreateTestChannels(tweaklessCommits bool) (
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
estimator := NewStaticFeeEstimator(6000, 0)
|
||||
estimator := chainfee.NewStaticEstimator(6000, 0)
|
||||
feePerKw, err := estimator.EstimateFeePerKW(1)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/shachain"
|
||||
)
|
||||
@@ -800,7 +801,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
||||
height: test.commitment.CommitHeight,
|
||||
ourBalance: test.commitment.LocalBalance,
|
||||
theirBalance: test.commitment.RemoteBalance,
|
||||
feePerKw: SatPerKWeight(test.commitment.FeePerKw),
|
||||
feePerKw: chainfee.SatPerKWeight(test.commitment.FeePerKw),
|
||||
dustLimit: tc.dustLimit,
|
||||
isOurs: true,
|
||||
}
|
||||
@@ -843,7 +844,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
||||
// Generate second-level HTLC transactions for HTLCs in
|
||||
// commitment tx.
|
||||
htlcResolutions, err := extractHtlcResolutions(
|
||||
SatPerKWeight(test.commitment.FeePerKw), true, signer,
|
||||
chainfee.SatPerKWeight(test.commitment.FeePerKw), true, signer,
|
||||
htlcs, keys, channel.localChanCfg, channel.remoteChanCfg,
|
||||
commitTx.TxHash(),
|
||||
)
|
||||
|
||||
+6
-5
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chanvalidate"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/shachain"
|
||||
@@ -89,11 +90,11 @@ type InitFundingReserveMsg struct {
|
||||
// of initial commitment transactions. In order to ensure timely
|
||||
// confirmation, it is recommended that this fee should be generous,
|
||||
// paying some multiple of the accepted base fee rate of the network.
|
||||
CommitFeePerKw SatPerKWeight
|
||||
CommitFeePerKw chainfee.SatPerKWeight
|
||||
|
||||
// FundingFeePerKw is the fee rate in sat/kw to use for the initial
|
||||
// funding transaction.
|
||||
FundingFeePerKw SatPerKWeight
|
||||
FundingFeePerKw chainfee.SatPerKWeight
|
||||
|
||||
// PushMSat is the number of milli-satoshis that should be pushed over
|
||||
// the responder as part of the initial channel creation.
|
||||
@@ -1323,7 +1324,7 @@ type coinSelection struct {
|
||||
// returned, and the value of the resulting funding output. This method locks
|
||||
// the selected outputs, and a function closure to unlock them in case of an
|
||||
// error is returned.
|
||||
func (l *LightningWallet) selectCoinsAndChange(feeRate SatPerKWeight,
|
||||
func (l *LightningWallet) selectCoinsAndChange(feeRate chainfee.SatPerKWeight,
|
||||
amt btcutil.Amount, minConfs int32, subtractFees bool) (
|
||||
*coinSelection, error) {
|
||||
|
||||
@@ -1485,7 +1486,7 @@ func selectInputs(amt btcutil.Amount, coins []*Utxo) (btcutil.Amount, []*Utxo, e
|
||||
// change output to fund amt satoshis, adhering to the specified fee rate. The
|
||||
// specified fee rate should be expressed in sat/kw for coin selection to
|
||||
// function properly.
|
||||
func coinSelect(feeRate SatPerKWeight, amt btcutil.Amount,
|
||||
func coinSelect(feeRate chainfee.SatPerKWeight, amt btcutil.Amount,
|
||||
coins []*Utxo) ([]*Utxo, btcutil.Amount, error) {
|
||||
|
||||
amtNeeded := amt
|
||||
@@ -1549,7 +1550,7 @@ func coinSelect(feeRate SatPerKWeight, amt btcutil.Amount,
|
||||
// coinSelectSubtractFees attempts to select coins such that we'll spend up to
|
||||
// amt in total after fees, adhering to the specified fee rate. The selected
|
||||
// coins, the final output and change values are returned.
|
||||
func coinSelectSubtractFees(feeRate SatPerKWeight, amt,
|
||||
func coinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
|
||||
dustLimit btcutil.Amount, coins []*Utxo) ([]*Utxo, btcutil.Amount,
|
||||
btcutil.Amount, error) {
|
||||
|
||||
|
||||
@@ -5,12 +5,15 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
// fundingFee is a helper method that returns the fee estimate used for a tx
|
||||
// with the given number of inputs and the optional change output. This matches
|
||||
// the estimate done by the wallet.
|
||||
func fundingFee(feeRate SatPerKWeight, numInput int, change bool) btcutil.Amount {
|
||||
func fundingFee(feeRate chainfee.SatPerKWeight, numInput int, // nolint:unparam
|
||||
change bool) btcutil.Amount {
|
||||
|
||||
var weightEstimate input.TxWeightEstimator
|
||||
|
||||
// All inputs.
|
||||
@@ -39,7 +42,7 @@ func fundingFee(feeRate SatPerKWeight, numInput int, change bool) btcutil.Amount
|
||||
func TestCoinSelect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const feeRate = SatPerKWeight(100)
|
||||
const feeRate = chainfee.SatPerKWeight(100)
|
||||
const dust = btcutil.Amount(100)
|
||||
|
||||
type testCase struct {
|
||||
@@ -185,7 +188,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const feeRate = SatPerKWeight(100)
|
||||
const feeRate = chainfee.SatPerKWeight(100)
|
||||
const dustLimit = btcutil.Amount(1000)
|
||||
const dust = btcutil.Amount(100)
|
||||
|
||||
|
||||
Reference in new issue
Block a user