Skip to content
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

contractcourt: Consider sweep cost when going on chain #3955

Draft
wants to merge 2 commits into
base: master
from

Conversation

@carlaKC
Copy link
Collaborator

carlaKC commented Jan 24, 2020

Smarter on chain heuristics, as specified in #1226.

This PR adds consideration for the cost of sweeping a htlc in the decision to go on chain. A htlc is considered economical if amount>sweep cost and uneconomical if amount<sweep cost.
This first iteration of smarter on chain logic examines the cost per htlc, rather than the cost of the sweep as a whole. Since we are not examining all the htlcs on the commitment, this change will have the effect of not going on chain for uneconomical htlcs, but will not prevent us from going on chain for an economical htlc.

Wondering about the side effects of this change for other impls/ older lnd nodes? From BOLT2:
if an HTLC which it offered is in either node's current commitment transaction, AND is past this timeout deadline: MUST fail the channel.
Would our peer not just go to chain anyway when they come back online? Going to test this locally and see how they interact.

Copy link
Collaborator

joostjager left a comment

I am still struggling a bit to understand the use case. If your peer doesn't manage the channel properly by leaving htlcs around, don't you want to close the channel anyway to recover your balance? There may be a uneconomical htlc output on the commit tx, but nothing can be done about that. Sweeping the output won't happen, because the sweeper skips it.


// Get the fee rate estimate (sat/kweight) that we estimate would be
// required to get this htlc on chain within the broadcast cutoff.
feeRateEstimate, err := feeEstimator(broadcastCutOff)

This comment has been minimized.

Copy link
@joostjager

joostjager Jan 24, 2020

Collaborator

I think we should use the fee that we are actually going to use if we'd go to chain now. Currently that is a fixed conf target that ignores how close we are to expiry.

This comment has been minimized.

Copy link
@joostjager

joostjager Jan 24, 2020

Collaborator

Also, if we force close, the htlcs need to be claimed first with the pre-signed second level transaction for which the fee is already set.

@carlaKC

This comment has been minimized.

Copy link
Collaborator Author

carlaKC commented Jan 24, 2020

I am still struggling a bit to understand the use case. If your peer doesn't manage the channel properly by leaving htlcs around, don't you want to close the channel anyway to recover your balance?

If they're just offline forever, you will want to close the channel anyway. But say you have a small htlc locked in with a mobile node, which is intermittently online, you might not want to go to the expense of going on chain when they might come back online and clear the htlc, specifically when it's for a very small amount. If they can come back online and fail the htlc, it is worthwhile having not going on chain, if they come back online after the timeout I think they will go on chain anyway (as per spec instruction) so it's the same outcome.

@joostjager

This comment has been minimized.

Copy link
Collaborator

joostjager commented Jan 24, 2020

And if you are the non-initiator of the channel, you will go on-chain even for a small amount because the remote party pays for it anyway?

I am also wondering whether it is a risk to evaluate the htlc added-fees individually. Doesn't that open up the possibility for an attacker to add the max number of htlcs, letting them all time out while offline and then come online, let the victim force close and then sweep back all the htlcs with the timeout txes? Can the total value of all htlcs be worth the attack?

@carlaKC

This comment has been minimized.

Copy link
Collaborator Author

carlaKC commented Jan 24, 2020

And if you are the non-initiator of the channel, you will go on-chain even for a small amount because the remote party pays for it anyway?

This isn't related to the fee we'd pay on the commitment transaction? (although that is another consideration for smarter on chain heuristics). We go on chain so that we can sweep the htlc timeout case. If the cost of that sweep is more than the amount, it's not worth our while to go on chain to claim it because we will lose money doing so.

open up the possibility for an attacker to add the max number of htlcs, letting them all time out while offline

From my understanding, if your peer wants to game you into force closing, they can achieve this as is with a single htlc and just go offline around timeout? So that isn't a new factor.

let the victim force close and then sweep back all the htlcs with the timeout txes

If we assess that each htlc uneconomical to sweep, I imagine it would be the case for the malicious party as well? But this definitely needs to be thought about, which is why I put this up early to start discussion.

@Roasbeef

This comment has been minimized.

Copy link
Member

Roasbeef commented Feb 3, 2020

We go on chain so that we can sweep the htlc timeout case. If the cost of that sweep is more than the amount, it's not worth our while to go on chain to claim it because we will lose money doing so.

Yeah if it's an incoming channel the remote party pays for the broadcast cost, but then we're burdened with additional HTLCs that we need to sweep, so more total chain costs total. When considering optimizations like this, I think we should be careful to not overly rely on the ideal/theoretical etiquette w.r.t our channel peers. We're building towards the world we'd like to see, but we aren't there quite yet.

This change is meant to achieve to goals:

  1. Maximize the utilization of the available bandwidth in the channel to the furthest extent. By delaying our on-chain broadcast, if the channel was highly trafficked (other than this one stuck HTLC), then it may be the case that the additional availability due to deferring broadcast may offset our on-chain costs.
  2. Avoid going to chain to sweep outputs that are border-line economical. When analyzing this case, one also needs to factor in the lost time-value by force closing the channel which starts the CSV clock ticking.

We should also note that these heuristics do have a failure mode when most of the commitment space is occupied by dormant limbo HTLCS, thereby reducing the effective goodput of a channel. However, it may the case that some (though degraded throughput) is better than none at all (closed channel, CSV delay).

The following commits will introduce more go to chain heuristics, so we
rename shouldGoOnChain to be more descriptive of the logic it uses.
@halseth

This comment has been minimized.

Copy link
Collaborator

halseth commented Feb 18, 2020

  1. Maximize the utilization of the available bandwidth in the channel to the furthest extent. By delaying our on-chain broadcast, if the channel was highly trafficked (other than this one stuck HTLC), then it may be the case that the additional availability due to deferring broadcast may offset our on-chain costs.

This relies on the channel being usable even though it has a stuck HTLC (stuck as never clears so that it times out). Is this even possible with an honest peer? The peer should cancel the HTLC, so I don't see how one can have open an usable channel with a peer that doesn't cancel such HTLCs.

@carlaKC carlaKC force-pushed the carlaKC:1226-shouldgoonchain branch from aa3ea3b to f0a2b3c Feb 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

4 participants
You can’t perform that action at this time.