-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[anchors] HTLC update fee clamp #4795
Changes from all commits
d57aa1d
02dcdf7
0070b64
a108643
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -366,6 +366,10 @@ type fundingConfig struct { | |
// RegisteredChains keeps track of all chains that have been registered | ||
// with the daemon. | ||
RegisteredChains *chainreg.ChainRegistry | ||
|
||
// MaxAnchorsCommitFeeRate is the max commitment fee rate we'll use as | ||
// the initiator for channels of the anchor type. | ||
MaxAnchorsCommitFeeRate chainfee.SatPerKWeight | ||
} | ||
|
||
// fundingManager acts as an orchestrator/bridge between the wallet's | ||
|
@@ -3123,16 +3127,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { | |
msg.pushAmt, msg.chainHash, peerKey.SerializeCompressed(), | ||
ourDustLimit, msg.minConfs) | ||
|
||
// First, we'll query the fee estimator for a fee that should get the | ||
// commitment transaction confirmed by the next few blocks (conf target | ||
// of 3). We target the near blocks here to ensure that we'll be able | ||
// to execute a timely unilateral channel closure if needed. | ||
commitFeePerKw, err := f.cfg.FeeEstimator.EstimateFeePerKW(3) | ||
if err != nil { | ||
msg.err <- err | ||
return | ||
} | ||
|
||
// We set the channel flags to indicate whether we want this channel to | ||
// be announced to the network. | ||
var channelFlags lnwire.FundingFlag | ||
|
@@ -3192,6 +3186,25 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { | |
commitType := commitmentType( | ||
msg.peer.LocalFeatures(), msg.peer.RemoteFeatures(), | ||
) | ||
|
||
// First, we'll query the fee estimator for a fee that should get the | ||
// commitment transaction confirmed by the next few blocks (conf target | ||
// of 3). We target the near blocks here to ensure that we'll be able | ||
// to execute a timely unilateral channel closure if needed. | ||
commitFeePerKw, err := f.cfg.FeeEstimator.EstimateFeePerKW(3) | ||
if err != nil { | ||
msg.err <- err | ||
return | ||
} | ||
|
||
// For anchor channels cap the initial commit fee rate at our defined | ||
// maximum. | ||
if commitType == lnwallet.CommitmentTypeAnchors && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think one other failure mode of this that we'll need to consider, is that until the second-level HTLCs are 1 sat/byte each, then rising fees can end up soft borking a channel until the fee wave subsides. However this is already more or less possible today if the fee estimate rises to a point that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is only the case if HTLCs regularly stagnate on the commitment transaction. One other more common impact of this change would be reducing the efficacy of MPP for smaller channels since at most (for all active concurrent payments), they'll be able to use only a handful of slots. It's difficult to try and have a better "risk assessment" based on the size of the channel itself, as then we'd also need to factor in exactly how the node is used as well. |
||
commitFeePerKw > f.cfg.MaxAnchorsCommitFeeRate { | ||
|
||
commitFeePerKw = f.cfg.MaxAnchorsCommitFeeRate | ||
} | ||
|
||
req := &lnwallet.InitFundingReserveMsg{ | ||
ChainHash: &msg.chainHash, | ||
PendingChanID: chanID, | ||
|
@@ -3224,6 +3237,36 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { | |
// SubtractFees=true. | ||
capacity := reservation.Capacity() | ||
|
||
// We'll use the current value of the channels and our default policy | ||
// to determine of required commitment constraints for the remote | ||
// party. | ||
chanReserve := f.cfg.RequiredRemoteChanReserve(capacity, ourDustLimit) | ||
|
||
// As a sanity check, we ensure that the user is not trying to open a | ||
// tiny anchor channel that would be unusable because of the fee siphon | ||
// check we do. | ||
if commitType == lnwallet.CommitmentTypeAnchors { | ||
timeoutFee := lnwallet.HtlcTimeoutFee( | ||
channeldb.AnchorOutputsBit, | ||
f.cfg.MaxAnchorsCommitFeeRate, | ||
) | ||
|
||
maxNumHtlcs := chanReserve / timeoutFee | ||
if maxNumHtlcs < lnwallet.MinAnchorHtlcSlots { | ||
if err := reservation.Cancel(); err != nil { | ||
fndgLog.Errorf("unable to cancel "+ | ||
"reservation: %v", err) | ||
} | ||
|
||
maxHtlcErr := fmt.Errorf("tiny channel, only room "+ | ||
"for %d HTLCs. Consider making a larger "+ | ||
"channel or reducing the max commit fee rate", | ||
maxNumHtlcs) | ||
msg.err <- maxHtlcErr | ||
return | ||
} | ||
} | ||
|
||
fndgLog.Infof("Target commit tx sat/kw for pendingID(%x): %v", chanID, | ||
int64(commitFeePerKw)) | ||
|
||
|
@@ -3279,11 +3322,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { | |
// request to the remote peer, kicking off the funding workflow. | ||
ourContribution := reservation.OurContribution() | ||
|
||
// Finally, we'll use the current value of the channels and our default | ||
// policy to determine of required commitment constraints for the | ||
// remote party. | ||
chanReserve := f.cfg.RequiredRemoteChanReserve(capacity, ourDustLimit) | ||
|
||
fndgLog.Infof("Starting funding workflow with %v for pending_id(%x), "+ | ||
"committype=%v", msg.peer.Address(), chanID, commitType) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're here, maybe also reduce this to 6-18 confs? As lately the 3 block estimate can be rather high
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean for all channel types, or only for anchors?
If it is for the general case, I would prefer to do it in a separate PR. Maybe even make it a config option?