lightning / blips

Bitcoin Lightning Improvement Proposals
132 stars 46 forks source link

blip-0033: commit fees channel flag #33

Open t-bast opened 4 months ago

t-bast commented 4 months ago

Standard lightning channels require the channel opener to pay the mining fees for the commitment transaction and mutual close transaction. This requirement forces the channel opener to contribute to the funding transaction and makes it impossible to open channels by only purchasing inbound liquidity from a remote node.

We want to allow nodes to opt into paying the commitment transaction fees even though they're not the channel opener.

t-bast commented 4 months ago

it seems that this is not a purely additive feature, but could interfere with other protocols/bLIPs.

That's true in theory, but in practice the risk of that should be pretty low, especially given that this bLIP is a temporary measure that won't be necessary anymore once we move to 0-fee commit txs. We can also just keep this bLIP updated whenever a feature is added to the BOLT that interferes with this bLIP, but there are none pending right now, so we're probably ok.

Given this is a rather fundamental change regarding a major assumption of the Lightning protocol, I wonder if it would be reasonable to add this as an optional feature to the BOLTs directly rather than making it a bLIP?

I'd like to avoid that since I hope we can instead switch to 0-fee commit txs and then remove this bLIP!

tnull commented 4 months ago

I'd like to avoid that since I hope we can instead switch to 0-fee commit txs and then remove this bLIP!

I think I'm a bit more skeptical regarding the zero-fee commitment transaction timeline. Yes, first steps towards package relay will ship in Bitcoin Core 0.28, but it will be quite some time (as in multiple years, no?) until we will be able to really lean on it and actually ship, let alone require zero-fee commit txs?

So, I'm not so sure how 'temporary' this change will be? And given how fundamental the change in the implementations' channel state machine/logic would be, it 'feels' to me a bit unsuited for a bLIP, but I might be wrong.

t-bast commented 4 months ago

I'd like to avoid cluttering the BOLTs with something that we know will be temporary (even if temporary means a couple of years), but if others also feel like this should be in the BOLTs, I'll move it there!

TheBlueMatt commented 4 months ago

This requirement forces the channel opener to contribute to the funding transaction and makes it impossible to open channels by only purchasing inbound liquidity from a remote node.

Not sure I understand the motivation here - if you want to buy inbound liquidity, you should have the inbound-liquidity-seller initiate the channel open from the lightning PoV. I assume that that liquidity seller is also the one who will want to pay the fees.

tnull commented 4 months ago

Not sure I understand the motivation here - if you want to buy inbound liquidity, you should have the inbound-liquidity-seller initiate the channel open from the lightning PoV. I assume that that liquidity seller is also the one who will want to pay the fees.

IIUC, this is necessary as we want to build on Liquidity Ads in which the buyer adds a request_funding TLV to the open_channel2 message, i.e., the channel opening is the liquidity request. FWIW, while it's indeed a bit weird for the on-the-fly flow, it is a bit more streamlined/efficient and as we don't need to spec additional messages/message formats and it's also nice that it saves us another RTT.

t-bast commented 4 months ago

Agreed with @tnull here, that's one of the reasons for it: in the liquidity ads flow, it's the initiator who is buying liquidity, doing it the other way around is clunky: you cannot send request_funding when accepting a channel, because the other peer has already announced their funding_amount in open_channel. So you'd need a pre-open message to tell the LSP to open/splice.

But that's actually what we initially tried for Phoenix: current Phoenix wallets send a please_open_channel message with details about the liquidity being bought and let the LSP send open_channel2. That requires more state tracking on both sides and forces us to pass custom TLV fields back and forth to keep track of the funding context. Having implemented both options (and having maintained one of them in production), I'm much happier with the one that relies on non_initiator_pays_commit_fees!

TheBlueMatt commented 4 months ago

I'm very, very, very much not a fan of touching the channel state machine just to avoid a round-trip when opening a non-JIT channel. Further, for JIT channels we need some kind of please_open_channel_when_i_get_a_payment message anyway, and splitting the JIT and non-JIT flows into two totally separate channel types and inverse negotiation flows also seems weird.

That requires more state tracking on both sides and forces us to pass custom TLV fields back and forth to keep track of the funding context. Having implemented both options (and having maintained one of them in production), I'm much happier with the one that relies on non_initiator_pays_commit_fees!

Yea, its definitely more code to add a new place to put state while claiming a channel, but we need that for JIT flows anyway. Given that code will already exist, why not use it for the non-JIT flow and avoid the need for channel changes?

t-bast commented 4 months ago

I'm very, very, very much not a fan of touching the channel state machine just to avoid a round-trip when opening a non-JIT channel.

The only thing it's changing in the channel state machine is that instead of gating operations based on whether the current node is the channel opener, you simply gate them on a different boolean that is defined immediately after exchanging open/accept (and should be stored in the static channel parameters). This is very straightforward, as the eclair PR shows!

Using some kind of please_open_channel message to make the liquidity seller initiate the open/splice requires much more changes to the channel funding state machine. It is quite inconsistent with the standard liquidity ads flow because it forces you to revert everything (provide_funding sent in open_channel2 instead of accept_channel2, which doesn't make any sense without a pre-open message).

Further, for JIT channels we need some kind of please_open_channel_when_i_get_a_payment message anyway, and splitting the JIT and non-JIT flows into two totally separate channel types and inverse negotiation flows also seems weird.

It doesn't have to be that way though once we start relying on liquidity ads, which contains all the negotiation we need? That was only true when there was no dual-funding nor liquidity ads protocol available (and is why we also initially shipped with a message like this)?

TheBlueMatt commented 4 months ago

The only thing it's changing in the channel state machine is that instead of gating operations based on whether the current node is the channel opener, you simply gate them on a different boolean that is defined immediately after exchanging open/accept (and should be stored in the static channel parameters). This is very straightforward, as the eclair PR shows!

I'm quite confident it'll be similarly simple code in LDK, though not quite as trivial since we have to pipe that bool through to multiple different systems (ie off and on-chain enforcement) and serialize it everywhere, but...

It doesn't have to be that way though once we start relying on liquidity ads, which contains all the negotiation we need? That was only true when there was no dual-funding nor liquidity ads protocol available (and is why we also initially shipped with a message like this)?

Hmm? Even with liquidity ads if I want to receive a JIT channel I need to exchange some message with the LSP, telling them I want to take advantage of their liquidity offer, track the fee I committed to pay, make sure I connect to this node even though I don't have a channel with them, etc, etc. I don't see how that changes this?

t-bast commented 4 months ago

Hmm? Even with liquidity ads if I want to receive a JIT channel I need to exchange some message with the LSP, telling them I want to take advantage of their liquidity offer, track the fee I committed to pay, make sure I connect to this node even though I don't have a channel with them, etc, etc. I don't see how that changes this?

What I mean is that you don't need any custom message for all of those points outside of the official BOLT messages:

That uses the standard liquidity ads flow and doesn't require additional changes to the channel state machine. Note that this is because liquidity purchases are always driven by the user (you could also design a different scheme where liquidity decisions are driven by the LSP, but I think that only works in a model where the user pays a % fee from every HTLC they receive - which could be an interesting model, but it's not the one we chose to experiment with).

dzdidi commented 4 months ago

@niftynei , @vincenzopalazzo told me that you might be the right person to give a feedback from the perspective of Core-Lightning

TheBlueMatt commented 1 month ago

After discussion at the summit we concluded that we can avoid this if we move to zero-fee commitment txn, which we agreed loosely to do.

t-bast commented 1 month ago

We will indeed be able to get rid of this with 0-fee commitment transactions. But since this is what we're currently using for Phoenix, I think it makes sense to keep the PR open so that it is specified somewhere (but no need to merge it). I'll close it when we're able to migrate to 0-fee commitment transactions.