sweep: create sweep parameters struct
Prepares for adding more input-specific sweep parameters.
This commit is contained in:
parent
e2bf6b49e9
commit
38adfd7ecc
@ -206,7 +206,7 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
c.log.Infof("sweeping commit output")
|
c.log.Infof("sweeping commit output")
|
||||||
|
|
||||||
feePref := sweep.FeePreference{ConfTarget: commitOutputConfTarget}
|
feePref := sweep.FeePreference{ConfTarget: commitOutputConfTarget}
|
||||||
resultChan, err := c.Sweeper.SweepInput(inp, feePref)
|
resultChan, err := c.Sweeper.SweepInput(inp, sweep.Params{Fee: feePref})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Errorf("unable to sweep input: %v", err)
|
c.log.Errorf("unable to sweep input: %v", err)
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ func newMockSweeper() *mockSweeper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockSweeper) SweepInput(input input.Input,
|
func (s *mockSweeper) SweepInput(input input.Input, params sweep.Params) (
|
||||||
feePreference sweep.FeePreference) (chan sweep.Result, error) {
|
chan sweep.Result, error) {
|
||||||
|
|
||||||
s.sweptInputs <- input
|
s.sweptInputs <- input
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ type OnionProcessor interface {
|
|||||||
// UtxoSweeper defines the sweep functions that contract court requires.
|
// UtxoSweeper defines the sweep functions that contract court requires.
|
||||||
type UtxoSweeper interface {
|
type UtxoSweeper interface {
|
||||||
// SweepInput sweeps inputs back into the wallet.
|
// SweepInput sweeps inputs back into the wallet.
|
||||||
SweepInput(input input.Input,
|
SweepInput(input input.Input, params sweep.Params) (chan sweep.Result,
|
||||||
feePreference sweep.FeePreference) (chan sweep.Result, error)
|
error)
|
||||||
|
|
||||||
// CreateSweepTx accepts a list of inputs and signs and generates a txn
|
// CreateSweepTx accepts a list of inputs and signs and generates a txn
|
||||||
// that spends from them. This method also makes an accurate fee
|
// that spends from them. This method also makes an accurate fee
|
||||||
|
@ -536,7 +536,7 @@ func (w *WalletKit) BumpFee(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
input := input.NewBaseInput(op, witnessType, signDesc, uint32(currentHeight))
|
input := input.NewBaseInput(op, witnessType, signDesc, uint32(currentHeight))
|
||||||
if _, err = w.cfg.Sweeper.SweepInput(input, feePreference); err != nil {
|
if _, err = w.cfg.Sweeper.SweepInput(input, sweep.Params{Fee: feePreference}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,14 @@ var (
|
|||||||
DefaultMaxSweepAttempts = 10
|
DefaultMaxSweepAttempts = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Params contains the parameters that control the sweeping process.
|
||||||
|
type Params struct {
|
||||||
|
// Fee is the fee preference of the client who requested the input to be
|
||||||
|
// swept. If a confirmation target is specified, then we'll map it into
|
||||||
|
// a fee rate whenever we attempt to cluster inputs for a sweep.
|
||||||
|
Fee FeePreference
|
||||||
|
}
|
||||||
|
|
||||||
// pendingInput is created when an input reaches the main loop for the first
|
// pendingInput is created when an input reaches the main loop for the first
|
||||||
// time. It tracks all relevant state that is needed for sweeping.
|
// time. It tracks all relevant state that is needed for sweeping.
|
||||||
type pendingInput struct {
|
type pendingInput struct {
|
||||||
@ -84,11 +92,8 @@ type pendingInput struct {
|
|||||||
// made to sweep this tx.
|
// made to sweep this tx.
|
||||||
publishAttempts int
|
publishAttempts int
|
||||||
|
|
||||||
// feePreference is the fee preference of the client who requested the
|
// params contains the parameters that control the sweeping process.
|
||||||
// input to be swept. If a confirmation target is specified, then we'll
|
params Params
|
||||||
// map it into a fee rate whenever we attempt to cluster inputs for a
|
|
||||||
// sweep.
|
|
||||||
feePreference FeePreference
|
|
||||||
|
|
||||||
// lastFeeRate is the most recent fee rate used for this input within a
|
// lastFeeRate is the most recent fee rate used for this input within a
|
||||||
// transaction broadcast to the network.
|
// transaction broadcast to the network.
|
||||||
@ -267,7 +272,7 @@ type Result struct {
|
|||||||
// SweepInput call and the sweeper main loop.
|
// SweepInput call and the sweeper main loop.
|
||||||
type sweepInputMessage struct {
|
type sweepInputMessage struct {
|
||||||
input input.Input
|
input input.Input
|
||||||
feePreference FeePreference
|
params Params
|
||||||
resultChan chan Result
|
resultChan chan Result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,25 +373,26 @@ func (s *UtxoSweeper) Stop() error {
|
|||||||
// Because it is an interface and we don't know what is exactly behind it, we
|
// Because it is an interface and we don't know what is exactly behind it, we
|
||||||
// cannot make a local copy in sweeper.
|
// cannot make a local copy in sweeper.
|
||||||
func (s *UtxoSweeper) SweepInput(input input.Input,
|
func (s *UtxoSweeper) SweepInput(input input.Input,
|
||||||
feePreference FeePreference) (chan Result, error) {
|
params Params) (chan Result, error) {
|
||||||
|
|
||||||
if input == nil || input.OutPoint() == nil || input.SignDesc() == nil {
|
if input == nil || input.OutPoint() == nil || input.SignDesc() == nil {
|
||||||
return nil, errors.New("nil input received")
|
return nil, errors.New("nil input received")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the client provided a sane fee preference.
|
// Ensure the client provided a sane fee preference.
|
||||||
if _, err := s.feeRateForPreference(feePreference); err != nil {
|
if _, err := s.feeRateForPreference(params.Fee); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Sweep request received: out_point=%v, witness_type=%v, "+
|
log.Infof("Sweep request received: out_point=%v, witness_type=%v, "+
|
||||||
"time_lock=%v, amount=%v, fee_preference=%v", input.OutPoint(),
|
"time_lock=%v, amount=%v, fee_preference=%v", input.OutPoint(),
|
||||||
input.WitnessType(), input.BlocksToMaturity(),
|
input.WitnessType(), input.BlocksToMaturity(),
|
||||||
btcutil.Amount(input.SignDesc().Output.Value), feePreference)
|
btcutil.Amount(input.SignDesc().Output.Value),
|
||||||
|
params.Fee)
|
||||||
|
|
||||||
sweeperInput := &sweepInputMessage{
|
sweeperInput := &sweepInputMessage{
|
||||||
input: input,
|
input: input,
|
||||||
feePreference: feePreference,
|
params: params,
|
||||||
resultChan: make(chan Result, 1),
|
resultChan: make(chan Result, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +476,7 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) {
|
|||||||
listeners: []chan Result{input.resultChan},
|
listeners: []chan Result{input.resultChan},
|
||||||
input: input.input,
|
input: input.input,
|
||||||
minPublishHeight: bestHeight,
|
minPublishHeight: bestHeight,
|
||||||
feePreference: input.feePreference,
|
params: input.params,
|
||||||
}
|
}
|
||||||
s.pendingInputs[outpoint] = pendInput
|
s.pendingInputs[outpoint] = pendInput
|
||||||
|
|
||||||
@ -653,7 +659,7 @@ func (s *UtxoSweeper) clusterBySweepFeeRate() []inputCluster {
|
|||||||
// First, we'll group together all inputs with similar fee rates. This
|
// First, we'll group together all inputs with similar fee rates. This
|
||||||
// is done by determining the fee rate bucket they should belong in.
|
// is done by determining the fee rate bucket they should belong in.
|
||||||
for op, input := range s.pendingInputs {
|
for op, input := range s.pendingInputs {
|
||||||
feeRate, err := s.feeRateForPreference(input.feePreference)
|
feeRate, err := s.feeRateForPreference(input.params.Fee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("Skipping input %v: %v", op, err)
|
log.Warnf("Skipping input %v: %v", op, err)
|
||||||
continue
|
continue
|
||||||
@ -1072,9 +1078,9 @@ func (s *UtxoSweeper) handleBumpFeeReq(req *bumpFeeReq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Updating fee preference for %v from %v to %v", req.input,
|
log.Debugf("Updating fee preference for %v from %v to %v", req.input,
|
||||||
pendingInput.feePreference, req.feePreference)
|
pendingInput.params.Fee, req.feePreference)
|
||||||
|
|
||||||
pendingInput.feePreference = req.feePreference
|
pendingInput.params.Fee = req.feePreference
|
||||||
|
|
||||||
// We'll reset the input's publish height to the current so that a new
|
// We'll reset the input's publish height to the current so that a new
|
||||||
// transaction can be created that replaces the transaction currently
|
// transaction can be created that replaces the transaction currently
|
||||||
|
@ -25,7 +25,7 @@ var (
|
|||||||
|
|
||||||
testMaxInputsPerTx = 3
|
testMaxInputsPerTx = 3
|
||||||
|
|
||||||
defaultFeePref = FeePreference{ConfTarget: 1}
|
defaultFeePref = Params{Fee: FeePreference{ConfTarget: 1}}
|
||||||
)
|
)
|
||||||
|
|
||||||
type sweeperTestContext struct {
|
type sweeperTestContext struct {
|
||||||
@ -354,7 +354,7 @@ func TestSuccess(t *testing.T) {
|
|||||||
ctx := createSweeperTestContext(t)
|
ctx := createSweeperTestContext(t)
|
||||||
|
|
||||||
// Sweeping an input without a fee preference should result in an error.
|
// Sweeping an input without a fee preference should result in an error.
|
||||||
_, err := ctx.sweeper.SweepInput(spendableInputs[0], FeePreference{})
|
_, err := ctx.sweeper.SweepInput(spendableInputs[0], Params{})
|
||||||
if err != ErrNoFeePreference {
|
if err != ErrNoFeePreference {
|
||||||
t.Fatalf("expected ErrNoFeePreference, got %v", err)
|
t.Fatalf("expected ErrNoFeePreference, got %v", err)
|
||||||
}
|
}
|
||||||
@ -1003,17 +1003,23 @@ func TestDifferentFeePreferences(t *testing.T) {
|
|||||||
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
||||||
|
|
||||||
input1 := spendableInputs[0]
|
input1 := spendableInputs[0]
|
||||||
resultChan1, err := ctx.sweeper.SweepInput(input1, highFeePref)
|
resultChan1, err := ctx.sweeper.SweepInput(
|
||||||
|
input1, Params{Fee: highFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
input2 := spendableInputs[1]
|
input2 := spendableInputs[1]
|
||||||
resultChan2, err := ctx.sweeper.SweepInput(input2, highFeePref)
|
resultChan2, err := ctx.sweeper.SweepInput(
|
||||||
|
input2, Params{Fee: highFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
input3 := spendableInputs[2]
|
input3 := spendableInputs[2]
|
||||||
resultChan3, err := ctx.sweeper.SweepInput(input3, lowFeePref)
|
resultChan3, err := ctx.sweeper.SweepInput(
|
||||||
|
input3, Params{Fee: lowFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1067,16 +1073,23 @@ func TestPendingInputs(t *testing.T) {
|
|||||||
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
||||||
|
|
||||||
input1 := spendableInputs[0]
|
input1 := spendableInputs[0]
|
||||||
resultChan1, err := ctx.sweeper.SweepInput(input1, highFeePref)
|
resultChan1, err := ctx.sweeper.SweepInput(
|
||||||
|
input1, Params{Fee: highFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
input2 := spendableInputs[1]
|
input2 := spendableInputs[1]
|
||||||
if _, err := ctx.sweeper.SweepInput(input2, highFeePref); err != nil {
|
_, err = ctx.sweeper.SweepInput(
|
||||||
|
input2, Params{Fee: highFeePref},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
input3 := spendableInputs[2]
|
input3 := spendableInputs[2]
|
||||||
resultChan3, err := ctx.sweeper.SweepInput(input3, lowFeePref)
|
resultChan3, err := ctx.sweeper.SweepInput(
|
||||||
|
input3, Params{Fee: lowFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1132,7 +1145,9 @@ func TestBumpFeeRBF(t *testing.T) {
|
|||||||
input := createTestInput(
|
input := createTestInput(
|
||||||
btcutil.SatoshiPerBitcoin, input.CommitmentTimeLock,
|
btcutil.SatoshiPerBitcoin, input.CommitmentTimeLock,
|
||||||
)
|
)
|
||||||
sweepResult, err := ctx.sweeper.SweepInput(&input, lowFeePref)
|
sweepResult, err := ctx.sweeper.SweepInput(
|
||||||
|
&input, Params{Fee: lowFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ type NurseryConfig struct {
|
|||||||
Store NurseryStore
|
Store NurseryStore
|
||||||
|
|
||||||
// Sweep sweeps an input back to the wallet.
|
// Sweep sweeps an input back to the wallet.
|
||||||
SweepInput func(input.Input, sweep.FeePreference) (chan sweep.Result, error)
|
SweepInput func(input.Input, sweep.Params) (chan sweep.Result, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// utxoNursery is a system dedicated to incubating time-locked outputs created
|
// utxoNursery is a system dedicated to incubating time-locked outputs created
|
||||||
@ -778,7 +778,9 @@ func (u *utxoNursery) sweepMatureOutputs(classHeight uint32,
|
|||||||
// passed in with disastrous consequences.
|
// passed in with disastrous consequences.
|
||||||
local := output
|
local := output
|
||||||
|
|
||||||
resultChan, err := u.cfg.SweepInput(&local, feePref)
|
resultChan, err := u.cfg.SweepInput(
|
||||||
|
&local, sweep.Params{Fee: feePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -983,7 +983,7 @@ func newMockSweeper(t *testing.T) *mockSweeper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockSweeper) sweepInput(input input.Input,
|
func (s *mockSweeper) sweepInput(input input.Input,
|
||||||
_ sweep.FeePreference) (chan sweep.Result, error) {
|
_ sweep.Params) (chan sweep.Result, error) {
|
||||||
|
|
||||||
utxnLog.Debugf("mockSweeper sweepInput called for %v", *input.OutPoint())
|
utxnLog.Debugf("mockSweeper sweepInput called for %v", *input.OutPoint())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user