Skip to content

WIP: make sweeper deadline aware#7549

Closed
yyforyongyu wants to merge 3 commits into
lightningnetwork:0-16-1-stagingfrom
yyforyongyu:deadline-aware
Closed

WIP: make sweeper deadline aware#7549
yyforyongyu wants to merge 3 commits into
lightningnetwork:0-16-1-stagingfrom
yyforyongyu:deadline-aware

Conversation

@yyforyongyu
Copy link
Copy Markdown
Member

@yyforyongyu yyforyongyu commented Mar 29, 2023

This is a very raw PoC PR to make the sweeper deadline-aware and fixes #4215.

Depends on:

In this PR, we extend the current sweeper to perform a fee bump if the input specifies it's deadline-aware. The sweeper will then continuously fee bump the sweeping tx in every new block if it's not confirmed.

An alternative approach would be fee bumping at the callsite, similar to how anchor sweeping is handled here. This approach IMO is not as good as the current one as a) the current approach has a deeper interface on sweeper and b) we can pre-define a set of fee bumping strategies so they can be easily applied based on specific conditions.

TODO:

@saubyk saubyk linked an issue Mar 29, 2023 that may be closed by this pull request
3 tasks
Comment thread sweep/fee_bump.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could use switch statement?

Comment thread sweep/fee_bump.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to watch for underflow here which would make target very large

Comment thread sweep/fee_bump.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If target = 1, then we're not technically behind the deadline as there is still 1 more block to go before the timelock expires.

Also, why is 2 the minimal value?

Comment thread sweep/fee_bump.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns a conf target, but in low-fee environments I believe the conf target can give the same feerate. We want to change the feerate up to some maximum % of the HTLC value here. I think instead this should only use a feerate rather than a conf-target. This would mean passing in a fee-rate from the timeout resolver.

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also need to be called up above when the input already exists in the sweeper?

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the deadline should be its own parameter because I think the current usage is that call-sites usually have a deadline but pass a conf target that is unrelated to the deadline. So adding the conf target to the current height might be too aggressive in some cases

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will block?

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing the strategy field?

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think we can get rid of Force, if it's uneconomical it's ok to give up

Comment thread sweep/sweeper.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this should only be for the deadline-aware inputs. The logic is a bit weird, but I think we can improve that later. We need to make sure that deadline-aware inputs don't stop after MaxSweepAttempts since they are going to be fee-bumping more since they are being re-submitted more in this function

@yyforyongyu yyforyongyu force-pushed the deadline-aware branch 3 times, most recently from 0be3133 to 30b61da Compare April 2, 2023 16:47
This commit adds a new service, `feeBumper` along with its interface
`Bumper`, to perform fee bumping over time sensitive inputs.

This commit focuses on building the framework for the bumper, and the
following commits will implement the actual strategies.
This commit adds a new strategy, `StrategyLinear`, to linearly increase
the fee rate used for a given input when the deadline approaches.
Copy link
Copy Markdown
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work porting this over from that other codebase! Left some inline comments, more specific to the lnd context. Main thing is that I think we can break up the new abstract strategies into an interface to further encapsulate the logic and allow for composition/re-use.

Comment thread sweep/log.go
log btclog.Logger

// feeLog is used by the fee bumper.
feeLog btclog.Logger
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could make this a sub-package to have it get its own distinct logger, and also be useable as a dep-minimized sub-module.

Comment thread sweep/sweeper.go

// Generate a pkScript to be used by the fee bumper for weight
// calculation.
pkScript, err := s.cfg.GenSweepScript()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we alternatively just make something that's P2TR sized? This way we don't need to extend the look ahead gap each time we restart.

Comment thread sweep/fee_bumper.go
}

// Add the input.
if err := weightEstimate.add(m.Input); err != nil {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to factor in the additional overhead of the type of inputs added to bump the transaction.

Comment thread sweep/fee_bumper.go

// Check if the request has already been processed.
//
// TODO(yy): allow overwrite?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or return a nil error unless we expect the caller to properly handle the returned ErrAlreadyMonitored.

Comment thread sweep/fee_bumper.go
feeRateUsed = feeRate
}

// If the requst doesn't specify a broadcast height, use the manager's
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requst -> request

Comment thread sweep/fee_bumper.go
var deadlineHeight uint32

// Calculate the deadline height if the conf target is set.
if req.ConfTarget != NoHeightInfo {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be ==? Since in this case, no conf target was specified, so we need to enforce a default conf target.

Comment thread sweep/fee_bumper.go
f.monitoredInputs.Range(func(_ *wire.OutPoint,
r *monitoredInput) bool {

f.wg.Add(1)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this should actually be done serially 🤔

Though with the way the sweeper works, all the goroutines will be serialized anyway, so it's nice to not have to block here so we can proceed other blocks/requests.

Comment thread sweep/fee_bumper.go
}

// Strategy specifies how the fee bump is performed.
type Strategy uint8
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A slightly different way to represent this would be to have Strategy itself be an interface with methods for: seeing it things need to be bumped, and suggesting the proper fee rate. This would allow us to further encapsulate the logic of each strategy, and each strategy can also maintain its own state to make better decisions.

Comment thread sweep/fee_bumper.go
}

// TODO(yy): cache the results?
func (f *feeBumper) feeRateForStrategyLinear(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we make this part of the strategy interface, then we can easily add caching there (though seems to be a premature optimization at this point imo).

@Roasbeef
Copy link
Copy Markdown
Member

Superseded by #8667

@Roasbeef Roasbeef closed this Apr 22, 2024
@yyforyongyu yyforyongyu deleted the deadline-aware branch April 23, 2024 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants