mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
contractcourt: specify deadline and budget for commit sweep
This commit is contained in:
parent
aa44197f88
commit
01fd4e5642
@ -13,17 +13,12 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
)
|
||||
|
||||
const (
|
||||
// commitOutputConfTarget is the default confirmation target we'll use
|
||||
// for sweeps of commit outputs that belong to us.
|
||||
commitOutputConfTarget = 6
|
||||
)
|
||||
|
||||
// commitSweepResolver is a resolver that will attempt to sweep the commitment
|
||||
// output paying to us, in the case that the remote party broadcasts their
|
||||
// version of the commitment transaction. We can sweep this output immediately,
|
||||
@ -347,12 +342,23 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
||||
// TODO(roasbeef): instead of ading ctrl block to the sign desc, make
|
||||
// new input type, have sweeper set it?
|
||||
|
||||
// With our input constructed, we'll now offer it to the
|
||||
// sweeper.
|
||||
c.log.Infof("sweeping commit output")
|
||||
// Calculate the budget for the sweeping this input.
|
||||
budget := calculateBudget(
|
||||
btcutil.Amount(inp.SignDesc().Output.Value),
|
||||
c.Budget.ToLocalRatio, c.Budget.ToLocal,
|
||||
)
|
||||
c.log.Infof("Sweeping commit output using budget=%v", budget)
|
||||
|
||||
feePref := sweep.FeeEstimateInfo{ConfTarget: commitOutputConfTarget}
|
||||
resultChan, err := c.Sweeper.SweepInput(inp, sweep.Params{Fee: feePref})
|
||||
// With our input constructed, we'll now offer it to the sweeper.
|
||||
resultChan, err := c.Sweeper.SweepInput(
|
||||
inp, sweep.Params{
|
||||
Budget: budget,
|
||||
|
||||
// Specify a nil deadline here as there's no time
|
||||
// pressure.
|
||||
DeadlineHeight: fn.None[int32](),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.log.Errorf("unable to sweep input: %v", err)
|
||||
|
||||
|
@ -129,15 +129,18 @@ func (s *mockSweeper) SweepInput(input input.Input, params sweep.Params) (
|
||||
|
||||
s.sweptInputs <- input
|
||||
|
||||
// TODO(yy): use `mock.Mock` to avoid the conversion.
|
||||
fee, ok := params.Fee.(sweep.FeeEstimateInfo)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected fee type: %T", params.Fee)
|
||||
}
|
||||
// TODO(yy): replace mockSweeper with `mock.Mock`.
|
||||
if params.Fee != nil {
|
||||
fee, ok := params.Fee.(sweep.FeeEstimateInfo)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected fee type: %T",
|
||||
params.Fee)
|
||||
}
|
||||
|
||||
// Update the deadlines used if it's set.
|
||||
if fee.ConfTarget != 0 {
|
||||
s.deadlines = append(s.deadlines, int(fee.ConfTarget))
|
||||
// Update the deadlines used if it's set.
|
||||
if fee.ConfTarget != 0 {
|
||||
s.deadlines = append(s.deadlines, int(fee.ConfTarget))
|
||||
}
|
||||
}
|
||||
|
||||
result := make(chan sweep.Result, 1)
|
||||
|
@ -111,3 +111,27 @@ func DefaultBudgetConfig() *BudgetConfig {
|
||||
NoDeadlineHTLCRatio: DefaultBudgetRatio,
|
||||
}
|
||||
}
|
||||
|
||||
// calculateBudget takes an output value, a configured ratio and budget value,
|
||||
// and returns the budget to use for sweeping the output. If the budget value
|
||||
// is set, it will be used as cap.
|
||||
func calculateBudget(value btcutil.Amount, ratio float64,
|
||||
max btcutil.Amount) btcutil.Amount {
|
||||
|
||||
// If ratio is not set, using the default value.
|
||||
if ratio == 0 {
|
||||
ratio = DefaultBudgetRatio
|
||||
}
|
||||
|
||||
budget := value.MulF64(ratio)
|
||||
|
||||
log.Tracef("Calculated budget=%v using value=%v, ratio=%v, cap=%v",
|
||||
budget, value, ratio, max)
|
||||
|
||||
if max != 0 && budget > max {
|
||||
log.Debugf("Calculated budget=%v is capped at %v", budget, max)
|
||||
return max
|
||||
}
|
||||
|
||||
return budget
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package contractcourt
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -81,3 +82,51 @@ func TestBudgetConfigValidate(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestCalculateBudget checks that the budget calculation works as expected.
|
||||
func TestCalculateBudget(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
value btcutil.Amount
|
||||
ratio float64
|
||||
max btcutil.Amount
|
||||
expected btcutil.Amount
|
||||
}{
|
||||
{
|
||||
// When the ratio is not specified, the default 0.5
|
||||
// should be used.
|
||||
name: "use default ratio",
|
||||
value: btcutil.Amount(1000),
|
||||
ratio: 0,
|
||||
max: 0,
|
||||
expected: btcutil.Amount(500),
|
||||
},
|
||||
{
|
||||
// When the ratio is specified, the default is not
|
||||
// used.
|
||||
name: "use specified ratio",
|
||||
value: btcutil.Amount(1000),
|
||||
ratio: 0.1,
|
||||
max: 0,
|
||||
expected: btcutil.Amount(100),
|
||||
},
|
||||
{
|
||||
// When the max is specified, the budget should be
|
||||
// capped at that value.
|
||||
name: "budget capped at max",
|
||||
value: btcutil.Amount(1000),
|
||||
ratio: 0.1,
|
||||
max: btcutil.Amount(1),
|
||||
expected: btcutil.Amount(1),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
budget := calculateBudget(tc.value, tc.ratio, tc.max)
|
||||
require.Equal(t, tc.expected, budget)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user