lnd
lnd copied to clipboard
[bug]: sweep: LinearFeeFunction off by one
LinearFeeFunction
doesn't return the max fee rate until after the deadline has been missed.
Example
Current block height is H
. An incoming HTLC has a cltv_expiry
of H + 10
, so the contractcourt sets deadline := H + 10
for the HTLC input.
We need to confirm our HTLC-Preimage no later than block H + 10
, or else we'll get into a bidding war with the channel peer since they can spend the timeout path after block H + 10
confirms.
LinearFeeFunction
should max out its fee rate after block H + 9
confirms since this is the last shot at meeting the deadline. Instead, LinearFeeFunction
waits to max out the fee rate until block H + 10
.
Severity
For typical deadlines 10+ blocks away, this is a minor problem. But in the extreme case of a next-block deadline, LinearFeeFunction
will return the min feerate instead of the max, which is quite bad.
@saubyk add to 18.0?
@saubyk add to 18.0?
makes sense. added.
cc: @yyforyongyu
But in the extreme case of a next-block deadline, LinearFeeFunction will return the min feerate instead of the max, which is quite bad.
What do you mean by saying next-block deadline? That we only have 1 block left till it times out? What is this min feerate?
What do you mean by saying next-block deadline? That we only have 1 block left till it times out? What is this min feerate?
Here's an example graph of the LinearFeeFunction
. The min feerate is the starting feerate. The max feerate is the ending feerate.
Now imagine we call SweepInput
with a deadline 1 block away. The fee function will be initialized with a width of 1 and starting feerate at the minimum of the feerate line. After 1 block (i.e. deadline missed), the feerate will be immediately bumped to the maximum of the feerate line.
But for this next-block deadline case, we really don't want a sloped line at all -- we want to start right at the maximum.
func (l *LinearFeeFunction) feeRateAtPosition(p uint32) chainfee.SatPerKWeight { if p >= l.width - 1 { return l.endingFeeRate } ... } does this suggestion fix the issue located in /sweep/fee_function.go