mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-27 14:11:04 +02:00
sweep: allow specifying starting fee rate for fee func
This commit is contained in:
@@ -570,6 +570,12 @@ func (b *BudgetAggregator) ClusterInputs(inputs InputsMap,
|
|||||||
// createInputSet takes a set of inputs which share the same deadline height
|
// createInputSet takes a set of inputs which share the same deadline height
|
||||||
// and turns them into a list of `InputSet`, each set is then used to create a
|
// and turns them into a list of `InputSet`, each set is then used to create a
|
||||||
// sweep transaction.
|
// sweep transaction.
|
||||||
|
//
|
||||||
|
// TODO(yy): by the time we call this method, all the invalid/uneconomical
|
||||||
|
// inputs have been filtered out, all the inputs have been sorted based on
|
||||||
|
// their budgets, and we are about to create input sets. The only thing missing
|
||||||
|
// here is, we need to group the inputs here even further based on whether
|
||||||
|
// their budgets can cover the starting fee rate used for this input set.
|
||||||
func (b *BudgetAggregator) createInputSets(inputs []SweeperInput,
|
func (b *BudgetAggregator) createInputSets(inputs []SweeperInput,
|
||||||
deadlineHeight int32) []InputSet {
|
deadlineHeight int32) []InputSet {
|
||||||
|
|
||||||
@@ -621,8 +627,10 @@ func (b *BudgetAggregator) createInputSets(inputs []SweeperInput,
|
|||||||
return sets
|
return sets
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterInputs filters out inputs that have a budget below the min relay fee
|
// filterInputs filters out inputs that have,
|
||||||
// or have a required output that's below the dust.
|
// - a budget below the min relay fee.
|
||||||
|
// - a budget below its requested starting fee.
|
||||||
|
// - a required output that's below the dust.
|
||||||
func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap {
|
func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap {
|
||||||
// Get the current min relay fee for this round.
|
// Get the current min relay fee for this round.
|
||||||
minFeeRate := b.estimator.RelayFeePerKW()
|
minFeeRate := b.estimator.RelayFeePerKW()
|
||||||
@@ -655,6 +663,19 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip inputs that has cannot cover its starting fees.
|
||||||
|
startingFeeRate := pi.params.StartingFeeRate.UnwrapOr(
|
||||||
|
chainfee.SatPerKWeight(0),
|
||||||
|
)
|
||||||
|
startingFee := startingFeeRate.FeeForWeight(int64(size))
|
||||||
|
if pi.params.Budget < startingFee {
|
||||||
|
log.Errorf("Skipped input=%v: has budget=%v, but the "+
|
||||||
|
"starting fee requires %v", op,
|
||||||
|
pi.params.Budget, minFee)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// If the input comes with a required tx out that is below
|
// If the input comes with a required tx out that is below
|
||||||
// dust, we won't add it.
|
// dust, we won't add it.
|
||||||
//
|
//
|
||||||
|
@@ -114,6 +114,10 @@ type BumpRequest struct {
|
|||||||
|
|
||||||
// MaxFeeRate is the maximum fee rate that can be used for fee bumping.
|
// MaxFeeRate is the maximum fee rate that can be used for fee bumping.
|
||||||
MaxFeeRate chainfee.SatPerKWeight
|
MaxFeeRate chainfee.SatPerKWeight
|
||||||
|
|
||||||
|
// StartingFeeRate is an optional parameter that can be used to specify
|
||||||
|
// the initial fee rate to use for the fee function.
|
||||||
|
StartingFeeRate fn.Option[chainfee.SatPerKWeight]
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxFeeRateAllowed returns the maximum fee rate allowed for the given
|
// MaxFeeRateAllowed returns the maximum fee rate allowed for the given
|
||||||
@@ -380,6 +384,7 @@ func (t *TxPublisher) initializeFeeFunction(
|
|||||||
// TODO(yy): return based on differet req.Strategy?
|
// TODO(yy): return based on differet req.Strategy?
|
||||||
return NewLinearFeeFunction(
|
return NewLinearFeeFunction(
|
||||||
maxFeeRateAllowed, confTarget, t.cfg.Estimator,
|
maxFeeRateAllowed, confTarget, t.cfg.Estimator,
|
||||||
|
req.StartingFeeRate,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@@ -110,8 +111,10 @@ var _ FeeFunction = (*LinearFeeFunction)(nil)
|
|||||||
// NewLinearFeeFunction creates a new linear fee function and initializes it
|
// NewLinearFeeFunction creates a new linear fee function and initializes it
|
||||||
// with a starting fee rate which is an estimated value returned from the fee
|
// with a starting fee rate which is an estimated value returned from the fee
|
||||||
// estimator using the initial conf target.
|
// estimator using the initial conf target.
|
||||||
func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, confTarget uint32,
|
func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight,
|
||||||
estimator chainfee.Estimator) (*LinearFeeFunction, error) {
|
confTarget uint32, estimator chainfee.Estimator,
|
||||||
|
startingFeeRate fn.Option[chainfee.SatPerKWeight]) (
|
||||||
|
*LinearFeeFunction, error) {
|
||||||
|
|
||||||
// If the deadline has already been reached, there's nothing the fee
|
// If the deadline has already been reached, there's nothing the fee
|
||||||
// function can do. In this case, we'll use the max fee rate
|
// function can do. In this case, we'll use the max fee rate
|
||||||
@@ -130,11 +133,17 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, confTarget uint32,
|
|||||||
estimator: estimator,
|
estimator: estimator,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimate the initial fee rate.
|
// If the caller specifies the starting fee rate, we'll use it instead
|
||||||
//
|
// of estimating it based on the deadline.
|
||||||
// NOTE: estimateFeeRate guarantees the returned fee rate is capped by
|
start, err := startingFeeRate.UnwrapOrFuncErr(
|
||||||
// the ending fee rate, so we don't need to worry about overpay.
|
func() (chainfee.SatPerKWeight, error) {
|
||||||
start, err := l.estimateFeeRate(confTarget)
|
// Estimate the initial fee rate.
|
||||||
|
//
|
||||||
|
// NOTE: estimateFeeRate guarantees the returned fee
|
||||||
|
// rate is capped by the ending fee rate, so we don't
|
||||||
|
// need to worry about overpay.
|
||||||
|
return l.estimateFeeRate(confTarget)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("estimate initial fee rate: %w", err)
|
return nil, fmt.Errorf("estimate initial fee rate: %w", err)
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package sweep
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -21,10 +22,12 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
estimatedFeeRate := chainfee.SatPerKWeight(500)
|
estimatedFeeRate := chainfee.SatPerKWeight(500)
|
||||||
minRelayFeeRate := chainfee.SatPerKWeight(100)
|
minRelayFeeRate := chainfee.SatPerKWeight(100)
|
||||||
confTarget := uint32(6)
|
confTarget := uint32(6)
|
||||||
|
noStartFeeRate := fn.None[chainfee.SatPerKWeight]()
|
||||||
|
startFeeRate := chainfee.SatPerKWeight(1000)
|
||||||
|
|
||||||
// Assert init fee function with zero conf value will end up using the
|
// Assert init fee function with zero conf value will end up using the
|
||||||
// max fee rate.
|
// max fee rate.
|
||||||
f, err := NewLinearFeeFunction(maxFeeRate, 0, estimator)
|
f, err := NewLinearFeeFunction(maxFeeRate, 0, estimator, noStartFeeRate)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
rt.NotNil(f)
|
rt.NotNil(f)
|
||||||
|
|
||||||
@@ -39,7 +42,9 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
estimator.On("EstimateFeePerKW", confTarget).Return(
|
estimator.On("EstimateFeePerKW", confTarget).Return(
|
||||||
chainfee.SatPerKWeight(0), errDummy).Once()
|
chainfee.SatPerKWeight(0), errDummy).Once()
|
||||||
|
|
||||||
f, err = NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator, noStartFeeRate,
|
||||||
|
)
|
||||||
rt.ErrorIs(err, errDummy)
|
rt.ErrorIs(err, errDummy)
|
||||||
rt.Nil(f)
|
rt.Nil(f)
|
||||||
|
|
||||||
@@ -53,7 +58,9 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
maxFeeRate+1, nil).Once()
|
maxFeeRate+1, nil).Once()
|
||||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||||
|
|
||||||
f, err = NewLinearFeeFunction(maxFeeRate, smallConf, estimator)
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, smallConf, estimator, noStartFeeRate,
|
||||||
|
)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
rt.NotNil(f)
|
rt.NotNil(f)
|
||||||
|
|
||||||
@@ -65,7 +72,9 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
maxFeeRate, nil).Once()
|
maxFeeRate, nil).Once()
|
||||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||||
|
|
||||||
f, err = NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator, noStartFeeRate,
|
||||||
|
)
|
||||||
rt.ErrorContains(err, "fee rate delta is zero")
|
rt.ErrorContains(err, "fee rate delta is zero")
|
||||||
rt.Nil(f)
|
rt.Nil(f)
|
||||||
|
|
||||||
@@ -75,7 +84,9 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
estimator.On("RelayFeePerKW").Return(minRelayFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(minRelayFeeRate).Once()
|
||||||
|
|
||||||
largeConf := uint32(1008)
|
largeConf := uint32(1008)
|
||||||
f, err = NewLinearFeeFunction(maxFeeRate, largeConf, estimator)
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, largeConf, estimator, noStartFeeRate,
|
||||||
|
)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
rt.NotNil(f)
|
rt.NotNil(f)
|
||||||
|
|
||||||
@@ -93,7 +104,9 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
estimatedFeeRate, nil).Once()
|
estimatedFeeRate, nil).Once()
|
||||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||||
|
|
||||||
f, err = NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator, noStartFeeRate,
|
||||||
|
)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
rt.NotNil(f)
|
rt.NotNil(f)
|
||||||
|
|
||||||
@@ -103,6 +116,22 @@ func TestLinearFeeFunctionNew(t *testing.T) {
|
|||||||
rt.Equal(estimatedFeeRate, f.currentFeeRate)
|
rt.Equal(estimatedFeeRate, f.currentFeeRate)
|
||||||
rt.NotZero(f.deltaFeeRate)
|
rt.NotZero(f.deltaFeeRate)
|
||||||
rt.Equal(confTarget, f.width)
|
rt.Equal(confTarget, f.width)
|
||||||
|
|
||||||
|
// Check a successfully created fee function using the specified
|
||||||
|
// starting fee rate.
|
||||||
|
//
|
||||||
|
// NOTE: by NOT mocking the fee estimator, we assert the
|
||||||
|
// estimateFeeRate is NOT called.
|
||||||
|
f, err = NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator, fn.Some(startFeeRate),
|
||||||
|
)
|
||||||
|
|
||||||
|
rt.NoError(err)
|
||||||
|
rt.NotNil(f)
|
||||||
|
|
||||||
|
// Assert the customized starting fee rate is used.
|
||||||
|
rt.Equal(startFeeRate, f.startingFeeRate)
|
||||||
|
rt.Equal(startFeeRate, f.currentFeeRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestLinearFeeFunctionFeeRateAtPosition checks the expected feerate is
|
// TestLinearFeeFunctionFeeRateAtPosition checks the expected feerate is
|
||||||
@@ -184,7 +213,10 @@ func TestLinearFeeFunctionIncrement(t *testing.T) {
|
|||||||
estimatedFeeRate, nil).Once()
|
estimatedFeeRate, nil).Once()
|
||||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||||
|
|
||||||
f, err := NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
f, err := NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator,
|
||||||
|
fn.None[chainfee.SatPerKWeight](),
|
||||||
|
)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
|
|
||||||
// We now increase the position from 1 to 9.
|
// We now increase the position from 1 to 9.
|
||||||
@@ -232,7 +264,10 @@ func TestLinearFeeFunctionIncreaseFeeRate(t *testing.T) {
|
|||||||
estimatedFeeRate, nil).Once()
|
estimatedFeeRate, nil).Once()
|
||||||
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once()
|
||||||
|
|
||||||
f, err := NewLinearFeeFunction(maxFeeRate, confTarget, estimator)
|
f, err := NewLinearFeeFunction(
|
||||||
|
maxFeeRate, confTarget, estimator,
|
||||||
|
fn.None[chainfee.SatPerKWeight](),
|
||||||
|
)
|
||||||
rt.NoError(err)
|
rt.NoError(err)
|
||||||
|
|
||||||
// If we are increasing the fee rate using the initial conf target, we
|
// If we are increasing the fee rate using the initial conf target, we
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
@@ -510,6 +511,13 @@ func (m *MockInputSet) Budget() btcutil.Amount {
|
|||||||
return args.Get(0).(btcutil.Amount)
|
return args.Get(0).(btcutil.Amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartingFeeRate returns the max starting fee rate found in the inputs.
|
||||||
|
func (m *MockInputSet) StartingFeeRate() fn.Option[chainfee.SatPerKWeight] {
|
||||||
|
args := m.Called()
|
||||||
|
|
||||||
|
return args.Get(0).(fn.Option[chainfee.SatPerKWeight])
|
||||||
|
}
|
||||||
|
|
||||||
// MockBumper is a mock implementation of the interface Bumper.
|
// MockBumper is a mock implementation of the interface Bumper.
|
||||||
type MockBumper struct {
|
type MockBumper struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
|
@@ -65,6 +65,10 @@ type Params struct {
|
|||||||
// without waiting for blocks to come to trigger the sweeping of
|
// without waiting for blocks to come to trigger the sweeping of
|
||||||
// inputs.
|
// inputs.
|
||||||
Immediate bool
|
Immediate bool
|
||||||
|
|
||||||
|
// StartingFeeRate is an optional parameter that can be used to specify
|
||||||
|
// the initial fee rate to use for the fee function.
|
||||||
|
StartingFeeRate fn.Option[chainfee.SatPerKWeight]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParamsUpdate contains a new set of parameters to update a pending sweep with.
|
// ParamsUpdate contains a new set of parameters to update a pending sweep with.
|
||||||
@@ -77,6 +81,10 @@ type ParamsUpdate struct {
|
|||||||
// Immediate indicates that the input should be swept immediately
|
// Immediate indicates that the input should be swept immediately
|
||||||
// without waiting for blocks to come.
|
// without waiting for blocks to come.
|
||||||
Immediate bool
|
Immediate bool
|
||||||
|
|
||||||
|
// StartingFeeRate is an optional parameter that can be used to specify
|
||||||
|
// the initial fee rate to use for the fee function.
|
||||||
|
StartingFeeRate fn.Option[chainfee.SatPerKWeight]
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human readable interpretation of the sweep parameters.
|
// String returns a human readable interpretation of the sweep parameters.
|
||||||
@@ -91,9 +99,9 @@ func (p Params) String() string {
|
|||||||
exclusiveGroup = fmt.Sprintf("%d", *p.ExclusiveGroup)
|
exclusiveGroup = fmt.Sprintf("%d", *p.ExclusiveGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("fee=%v, immediate=%v, exclusive_group=%v, budget=%v, "+
|
return fmt.Sprintf("startingFeeRate=%v, immediate=%v, "+
|
||||||
"deadline=%v", p.Fee, p.Immediate, exclusiveGroup, p.Budget,
|
"exclusive_group=%v, budget=%v, deadline=%v", p.StartingFeeRate,
|
||||||
deadline)
|
p.Immediate, exclusiveGroup, p.Budget, deadline)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SweepState represents the current state of a pending input.
|
// SweepState represents the current state of a pending input.
|
||||||
@@ -830,6 +838,7 @@ func (s *UtxoSweeper) sweep(set InputSet) error {
|
|||||||
DeadlineHeight: set.DeadlineHeight(),
|
DeadlineHeight: set.DeadlineHeight(),
|
||||||
DeliveryAddress: s.currentOutputScript,
|
DeliveryAddress: s.currentOutputScript,
|
||||||
MaxFeeRate: s.cfg.MaxFeeRate.FeePerKWeight(),
|
MaxFeeRate: s.cfg.MaxFeeRate.FeePerKWeight(),
|
||||||
|
StartingFeeRate: set.StartingFeeRate(),
|
||||||
// TODO(yy): pass the strategy here.
|
// TODO(yy): pass the strategy here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2734,9 +2734,13 @@ func TestSweepPendingInputs(t *testing.T) {
|
|||||||
setNeedWallet.On("Inputs").Return(nil).Times(4)
|
setNeedWallet.On("Inputs").Return(nil).Times(4)
|
||||||
setNeedWallet.On("DeadlineHeight").Return(testHeight).Once()
|
setNeedWallet.On("DeadlineHeight").Return(testHeight).Once()
|
||||||
setNeedWallet.On("Budget").Return(btcutil.Amount(1)).Once()
|
setNeedWallet.On("Budget").Return(btcutil.Amount(1)).Once()
|
||||||
|
setNeedWallet.On("StartingFeeRate").Return(
|
||||||
|
fn.None[chainfee.SatPerKWeight]()).Once()
|
||||||
normalSet.On("Inputs").Return(nil).Times(4)
|
normalSet.On("Inputs").Return(nil).Times(4)
|
||||||
normalSet.On("DeadlineHeight").Return(testHeight).Once()
|
normalSet.On("DeadlineHeight").Return(testHeight).Once()
|
||||||
normalSet.On("Budget").Return(btcutil.Amount(1)).Once()
|
normalSet.On("Budget").Return(btcutil.Amount(1)).Once()
|
||||||
|
normalSet.On("StartingFeeRate").Return(
|
||||||
|
fn.None[chainfee.SatPerKWeight]()).Once()
|
||||||
|
|
||||||
// Make pending inputs for testing. We don't need real values here as
|
// Make pending inputs for testing. We don't need real values here as
|
||||||
// the returned clusters are mocked.
|
// the returned clusters are mocked.
|
||||||
|
@@ -77,6 +77,10 @@ type InputSet interface {
|
|||||||
// Budget givens the total amount that can be used as fees by this
|
// Budget givens the total amount that can be used as fees by this
|
||||||
// input set.
|
// input set.
|
||||||
Budget() btcutil.Amount
|
Budget() btcutil.Amount
|
||||||
|
|
||||||
|
// StartingFeeRate returns the max starting fee rate found in the
|
||||||
|
// inputs.
|
||||||
|
StartingFeeRate() fn.Option[chainfee.SatPerKWeight]
|
||||||
}
|
}
|
||||||
|
|
||||||
type txInputSetState struct {
|
type txInputSetState struct {
|
||||||
@@ -205,6 +209,13 @@ func (t *txInputSet) DeadlineHeight() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartingFeeRate returns the max starting fee rate found in the inputs.
|
||||||
|
//
|
||||||
|
// NOTE: this field is only used for `BudgetInputSet`.
|
||||||
|
func (t *txInputSet) StartingFeeRate() fn.Option[chainfee.SatPerKWeight] {
|
||||||
|
return fn.None[chainfee.SatPerKWeight]()
|
||||||
|
}
|
||||||
|
|
||||||
// NeedWalletInput returns true if the input set needs more wallet inputs.
|
// NeedWalletInput returns true if the input set needs more wallet inputs.
|
||||||
func (t *txInputSet) NeedWalletInput() bool {
|
func (t *txInputSet) NeedWalletInput() bool {
|
||||||
return !t.enoughInput()
|
return !t.enoughInput()
|
||||||
@@ -800,3 +811,21 @@ func (b *BudgetInputSet) Inputs() []input.Input {
|
|||||||
|
|
||||||
return inputs
|
return inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartingFeeRate returns the max starting fee rate found in the inputs.
|
||||||
|
//
|
||||||
|
// NOTE: part of the InputSet interface.
|
||||||
|
func (b *BudgetInputSet) StartingFeeRate() fn.Option[chainfee.SatPerKWeight] {
|
||||||
|
maxFeeRate := chainfee.SatPerKWeight(0)
|
||||||
|
startingFeeRate := fn.None[chainfee.SatPerKWeight]()
|
||||||
|
|
||||||
|
for _, inp := range b.inputs {
|
||||||
|
feerate := inp.params.StartingFeeRate.UnwrapOr(0)
|
||||||
|
if feerate > maxFeeRate {
|
||||||
|
maxFeeRate = feerate
|
||||||
|
startingFeeRate = fn.Some(maxFeeRate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return startingFeeRate
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user