sweep: allow updating all sweep parameters
This is a preparation for adding additional parameters besides the fee preference.
This commit is contained in:
parent
280611ab6e
commit
16832cefa3
@ -485,7 +485,11 @@ func (w *WalletKit) BumpFee(ctx context.Context,
|
|||||||
// bump its fee, which will result in a replacement transaction (RBF)
|
// bump its fee, which will result in a replacement transaction (RBF)
|
||||||
// being broadcast. If it is not aware of the input however,
|
// being broadcast. If it is not aware of the input however,
|
||||||
// lnwallet.ErrNotMine is returned.
|
// lnwallet.ErrNotMine is returned.
|
||||||
_, err = w.cfg.Sweeper.BumpFee(*op, feePreference)
|
params := sweep.Params{
|
||||||
|
Fee: feePreference,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.cfg.Sweeper.UpdateParams(*op, params)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
return &BumpFeeResponse{}, nil
|
return &BumpFeeResponse{}, nil
|
||||||
|
@ -69,6 +69,11 @@ type Params struct {
|
|||||||
Fee FeePreference
|
Fee FeePreference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human readable interpretation of the sweep parameters.
|
||||||
|
func (p Params) String() string {
|
||||||
|
return fmt.Sprintf("fee=%v", p.Fee)
|
||||||
|
}
|
||||||
|
|
||||||
// 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 wraps the input and tracks all relevant state that is needed for
|
// time. It wraps the input and tracks all relevant state that is needed for
|
||||||
// sweeping.
|
// sweeping.
|
||||||
@ -151,17 +156,17 @@ type PendingInput struct {
|
|||||||
Params Params
|
Params Params
|
||||||
}
|
}
|
||||||
|
|
||||||
// bumpFeeReq is an internal message we'll use to represent an external caller's
|
// updateReq is an internal message we'll use to represent an external caller's
|
||||||
// intent to bump the fee rate of a given input.
|
// intent to update the sweep parameters of a given input.
|
||||||
type bumpFeeReq struct {
|
type updateReq struct {
|
||||||
input wire.OutPoint
|
input wire.OutPoint
|
||||||
feePreference FeePreference
|
params Params
|
||||||
responseChan chan *bumpFeeResp
|
responseChan chan *updateResp
|
||||||
}
|
}
|
||||||
|
|
||||||
// bumpFeeResp is an internal message we'll use to hand off the response of a
|
// updateResp is an internal message we'll use to hand off the response of a
|
||||||
// bumpFeeReq from the UtxoSweeper's main event loop back to the caller.
|
// updateReq from the UtxoSweeper's main event loop back to the caller.
|
||||||
type bumpFeeResp struct {
|
type updateResp struct {
|
||||||
resultChan chan Result
|
resultChan chan Result
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
@ -181,9 +186,9 @@ type UtxoSweeper struct {
|
|||||||
// UtxoSweeper is attempting to sweep.
|
// UtxoSweeper is attempting to sweep.
|
||||||
pendingSweepsReqs chan *pendingSweepsReq
|
pendingSweepsReqs chan *pendingSweepsReq
|
||||||
|
|
||||||
// bumpFeeReqs is a channel that will be sent requests by external
|
// updateReqs is a channel that will be sent requests by external
|
||||||
// callers who wish to bump the fee rate of a given input.
|
// callers who wish to bump the fee rate of a given input.
|
||||||
bumpFeeReqs chan *bumpFeeReq
|
updateReqs chan *updateReq
|
||||||
|
|
||||||
// pendingInputs is the total set of inputs the UtxoSweeper has been
|
// pendingInputs is the total set of inputs the UtxoSweeper has been
|
||||||
// requested to sweep.
|
// requested to sweep.
|
||||||
@ -290,7 +295,7 @@ func New(cfg *UtxoSweeperConfig) *UtxoSweeper {
|
|||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
newInputs: make(chan *sweepInputMessage),
|
newInputs: make(chan *sweepInputMessage),
|
||||||
spendChan: make(chan *chainntnfs.SpendDetail),
|
spendChan: make(chan *chainntnfs.SpendDetail),
|
||||||
bumpFeeReqs: make(chan *bumpFeeReq),
|
updateReqs: make(chan *updateReq),
|
||||||
pendingSweepsReqs: make(chan *pendingSweepsReq),
|
pendingSweepsReqs: make(chan *pendingSweepsReq),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
pendingInputs: make(pendingInputs),
|
pendingInputs: make(pendingInputs),
|
||||||
@ -575,9 +580,9 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) {
|
|||||||
|
|
||||||
// A new external request has been received to bump the fee rate
|
// A new external request has been received to bump the fee rate
|
||||||
// of a given input.
|
// of a given input.
|
||||||
case req := <-s.bumpFeeReqs:
|
case req := <-s.updateReqs:
|
||||||
resultChan, err := s.handleBumpFeeReq(req, bestHeight)
|
resultChan, err := s.handleUpdateReq(req, bestHeight)
|
||||||
req.responseChan <- &bumpFeeResp{
|
req.responseChan <- &updateResp{
|
||||||
resultChan: resultChan,
|
resultChan: resultChan,
|
||||||
err: err,
|
err: err,
|
||||||
}
|
}
|
||||||
@ -1044,28 +1049,28 @@ func (s *UtxoSweeper) handlePendingSweepsReq(
|
|||||||
return pendingInputs
|
return pendingInputs
|
||||||
}
|
}
|
||||||
|
|
||||||
// BumpFee allows bumping the fee of an input being swept by the UtxoSweeper
|
// UpdateParams allows updating the sweep parameters of a pending input in the
|
||||||
// according to the provided fee preference. The new fee preference will be used
|
// UtxoSweeper. This function can be used to provide an updated fee preference
|
||||||
// for a new sweep transaction of the input that will act as a replacement
|
// that will be used for a new sweep transaction of the input that will act as a
|
||||||
// transaction (RBF) of the original sweeping transaction, if any.
|
// replacement transaction (RBF) of the original sweeping transaction, if any.
|
||||||
//
|
//
|
||||||
// NOTE: This currently doesn't do any fee rate validation to ensure that a bump
|
// NOTE: This currently doesn't do any fee rate validation to ensure that a bump
|
||||||
// is actually successful. The responsibility of doing so should be handled by
|
// is actually successful. The responsibility of doing so should be handled by
|
||||||
// the caller.
|
// the caller.
|
||||||
func (s *UtxoSweeper) BumpFee(input wire.OutPoint,
|
func (s *UtxoSweeper) UpdateParams(input wire.OutPoint,
|
||||||
feePreference FeePreference) (chan Result, error) {
|
params Params) (chan Result, error) {
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
responseChan := make(chan *bumpFeeResp, 1)
|
responseChan := make(chan *updateResp, 1)
|
||||||
select {
|
select {
|
||||||
case s.bumpFeeReqs <- &bumpFeeReq{
|
case s.updateReqs <- &updateReq{
|
||||||
input: input,
|
input: input,
|
||||||
feePreference: feePreference,
|
params: params,
|
||||||
responseChan: responseChan,
|
responseChan: responseChan,
|
||||||
}:
|
}:
|
||||||
case <-s.quit:
|
case <-s.quit:
|
||||||
return nil, ErrSweeperShuttingDown
|
return nil, ErrSweeperShuttingDown
|
||||||
@ -1079,9 +1084,9 @@ func (s *UtxoSweeper) BumpFee(input wire.OutPoint,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleBumpFeeReq handles a bump fee request by simply updating the inputs fee
|
// handleUpdateReq handles an update request by simply updating the sweep
|
||||||
// preference. Currently, no validation is done on the new fee preference to
|
// parameters of the pending input. Currently, no validation is done on the new
|
||||||
// ensure it will properly create a replacement transaction.
|
// fee preference to ensure it will properly create a replacement transaction.
|
||||||
//
|
//
|
||||||
// TODO(wilmer):
|
// TODO(wilmer):
|
||||||
// * Validate fee preference to ensure we'll create a valid replacement
|
// * Validate fee preference to ensure we'll create a valid replacement
|
||||||
@ -1090,8 +1095,8 @@ func (s *UtxoSweeper) BumpFee(input wire.OutPoint,
|
|||||||
// * Ensure we don't combine this input with any other unconfirmed inputs that
|
// * Ensure we don't combine this input with any other unconfirmed inputs that
|
||||||
// did not exist in the original sweep transaction, resulting in an invalid
|
// did not exist in the original sweep transaction, resulting in an invalid
|
||||||
// replacement transaction.
|
// replacement transaction.
|
||||||
func (s *UtxoSweeper) handleBumpFeeReq(req *bumpFeeReq,
|
func (s *UtxoSweeper) handleUpdateReq(req *updateReq, bestHeight int32) (
|
||||||
bestHeight int32) (chan Result, error) {
|
chan Result, error) {
|
||||||
|
|
||||||
// If the UtxoSweeper is already trying to sweep this input, then we can
|
// If the UtxoSweeper is already trying to sweep this input, then we can
|
||||||
// simply just increase its fee rate. This will allow the input to be
|
// simply just increase its fee rate. This will allow the input to be
|
||||||
@ -1103,10 +1108,10 @@ func (s *UtxoSweeper) handleBumpFeeReq(req *bumpFeeReq,
|
|||||||
return nil, lnwallet.ErrNotMine
|
return nil, lnwallet.ErrNotMine
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Updating fee preference for %v from %v to %v", req.input,
|
log.Debugf("Updating sweep parameters for %v from %v to %v", req.input,
|
||||||
pendingInput.params.Fee, req.feePreference)
|
pendingInput.params, req.params)
|
||||||
|
|
||||||
pendingInput.params.Fee = req.feePreference
|
pendingInput.params = req.params
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -1178,7 +1178,9 @@ func TestBumpFeeRBF(t *testing.T) {
|
|||||||
|
|
||||||
// We'll first try to bump the fee of an output currently unknown to the
|
// We'll first try to bump the fee of an output currently unknown to the
|
||||||
// UtxoSweeper. Doing so should result in a lnwallet.ErrNotMine error.
|
// UtxoSweeper. Doing so should result in a lnwallet.ErrNotMine error.
|
||||||
bumpResult, err := ctx.sweeper.BumpFee(wire.OutPoint{}, lowFeePref)
|
_, err := ctx.sweeper.UpdateParams(
|
||||||
|
wire.OutPoint{}, Params{Fee: lowFeePref},
|
||||||
|
)
|
||||||
if err != lnwallet.ErrNotMine {
|
if err != lnwallet.ErrNotMine {
|
||||||
t.Fatalf("expected error lnwallet.ErrNotMine, got \"%v\"", err)
|
t.Fatalf("expected error lnwallet.ErrNotMine, got \"%v\"", err)
|
||||||
}
|
}
|
||||||
@ -1206,12 +1208,14 @@ func TestBumpFeeRBF(t *testing.T) {
|
|||||||
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate
|
||||||
|
|
||||||
// We should expect to see an error if a fee preference isn't provided.
|
// We should expect to see an error if a fee preference isn't provided.
|
||||||
_, err = ctx.sweeper.BumpFee(*input.OutPoint(), FeePreference{})
|
_, err = ctx.sweeper.UpdateParams(*input.OutPoint(), Params{})
|
||||||
if err != ErrNoFeePreference {
|
if err != ErrNoFeePreference {
|
||||||
t.Fatalf("expected ErrNoFeePreference, got %v", err)
|
t.Fatalf("expected ErrNoFeePreference, got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bumpResult, err = ctx.sweeper.BumpFee(*input.OutPoint(), highFeePref)
|
bumpResult, err := ctx.sweeper.UpdateParams(
|
||||||
|
*input.OutPoint(), Params{Fee: highFeePref},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to bump input's fee: %v", err)
|
t.Fatalf("unable to bump input's fee: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user