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

Extensible liquidity ads rates #1153

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

t-bast
Copy link
Collaborator

@t-bast t-bast commented Apr 15, 2024

Add the ability to advertise rates at which nodes wish to sell their liquidity. Buyers can then connect to sellers and request liquidity, at one of the advertised rates.

This can be used when creating a dual-funded channel, where both participants contribute to the funding transaction, and one of them is paid for (some of) their contribution. This can also be used to splice additional liquidity into existing channels, when splicing is supported.

We support multiple types of liquidity leases, and use an extensible format to allow adding new types of leases in the future. This can be useful to allow different ways of paying the lease fees, and different constraints on the seller or buyer side. Reviewers should take a look at the first commit to see how multiple lease_types can be defined.

LSPs may for example want to offer leases where fees are not paid immediately when creating the transaction, but instead taken from every future HTLC relayed on that channel using something similar to lightning/blips#25. This also creates that ability for bLIPs to introduce new types of liquidity leases, without affecting the BOLTs.

The existing lease type doesn't add any constraints to the commitment transactions. The lease duration isn't protected by script opcodes, which means that the seller could immediately close the channel, or splice funds out. It is up to the buyer to then blacklist that seller. We can in the future modify the commitment transactions to restrict the seller: that can be done by introducing a new lease_type if it is considered useful.

This introduces a few subtypes, that can be hard to read in the spec format: that's why a test vector is included that makes it easier to see how data is nested, and how it is encoded. An implementation of the codecs for those types can be found in ACINQ/eclair#2848 which may be helpful to reviewers.

This PR is a concurrent design for #1145.

Credits to @niftynei will be added in the commit messages once we're ready to merge this PR.

07-routing-gossip.md Outdated Show resolved Hide resolved
@t-bast
Copy link
Collaborator Author

t-bast commented Apr 15, 2024

@TheBlueMatt I believe this kind of design leaves enough room for introducing different types of leases and fee mechanisms, and would make it easy to support all LSP use-cases. It also makes it easy for bLIPs to introduce lease types, that would keep using most of the liquidity ads mechanisms. Let me know what you think!

07-routing-gossip.md Outdated Show resolved Hide resolved
t-bast added a commit to ACINQ/eclair that referenced this pull request Apr 15, 2024
Add types and codecs for the extensible liquidity ads format proposed
in lightning/bolts#1153.
Copy link
Contributor

@JssDWt JssDWt left a comment

Choose a reason for hiding this comment

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

From the first look this looks like a good extensible model for channel leases. I didn't find any obvious gaps.

fees to the seller for the funding they provide to the channel based on the
agreed upon `funding_lease_fee`.

The lease fee is taken from the buyer's funding inputs and added to the
Copy link
Contributor

Choose a reason for hiding this comment

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

In this case the client already needs funds available onchain to receive the channel. If the way the lease fee is taken would be defined by TLV types as well, there could be multiple options for payment methods. I'm thinking for example JIT channels, where the fee is taken from htlcs.

EDIT: I suppose in that case the funding_lease_fee would be zero and the payment method can go in a TLV elsewhere.

Copy link
Collaborator Author

@t-bast t-bast Apr 17, 2024

Choose a reason for hiding this comment

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

In the case where the buyer doesn't have any funds (either on-chain or in an existing channel) to pay the fees, you wouldn't use one of the lease types provided here. That's where an on-the-fly liquidity bLIP would introduce a new lease type that would pay the fees by subtracting them from the HTLC amount (or from all future HTLCs), most likely based on lightning/blips#25

Copy link
Contributor

Choose a reason for hiding this comment

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

It seem that currently we require all lease types to incorporate funding_lease_fee as otherwise the client wouldn't be able to calculate the fee in advance, allowing it to decide whether to accept or reject an incoming HTLC from which the seller withheld an amount through lightning/blips#25.

I wonder if we're fine with this, or if it will be too inflexible going forward. Should we rather clarify that for each lease type the fee calculation needs to be spec'd too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It seem that currently we require all lease types to incorporate funding_lease_fee

This is only the case for the two lease_types that are currently defined, but a different lease_type doesn't need to to incorporate a funding_lease_fee at all, we're free to do whatever we want in future lease_types.

For example, a new lease_type for on-the-fly funding where the buyer doesn't have any funds yet could look like this:

1. `lease_type`: 129 (`on_the_fly_funding_lease`)
2. data:
    * [`u32`:`htlc_base_fee_msat`]
    * [`u16`:`htlc_proportional_fee`]

Where the buyer doesn't pay any fee when the channel is created (or spliced) but any future HTLC relayed to the buyer is relayed with htlc_base_fee_msat and htlc_proportional_fee removed and paid to the seller. The buyer doesn't know exactly how much this specific funding attempt is costing him, but it's just a different way of thinking about things: the buyer is instead paying a fee on all HTLCs received that implicitly covers getting liquidity to receive those payments.

Or it could be done in a lot of different ways, anything is possible really!

Copy link
Contributor

Choose a reason for hiding this comment

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

This is only the case for the two lease_types that are currently defined, but a different lease_type doesn't need to to incorporate a funding_lease_fee at all, we're free to do whatever we want in future lease_types.

Ah, but the current description in the Paying the funding_lease_fee`` section seems specific to the initial funding_lease_fee-based lease type? My main point is that independently from the lease type, the client will always need to be able to calculate the withheld fee, so for any additional lease types we add we should also clearly define how the fee will be calculated for them, i.e. we'll need specific `Paying the ..` sections for each of them. Just mentioning this as the current structure of the document doesn't seem setup with this in mind?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think you're talking about a model where each JIT-channel has a specific fee, defined when the channel is bought? And then this fee is slowly paid using lightning/blips#25 as HTLCs come in, and may be spread across multiple future HTLCs (in case the first HTLCs relayed are smaller than the fee)? And once the fee is fully paid, the channel seller stops claiming some of the HTLC amount they relay to the buyer? If that's the kind of flow you're discussing, then you're right, both sides need to know at channel or splice creation time the exact fee that is owed by the buyer to the seller. That's easily done though? And then each side needs to keep track of how much of that fee has already been paid, which should be simple enough as well?

The model I'm discussing is different. We can imagine a wallet that tells its users "You'll pay a 1% fee on every payment you receive, and nothing else, and liquidity will be handled for you automatically". In that case there isn't a specific fee associated to each funding amount.

I think we want to be able to support both scenarios, right? So we should be very liberal in what we allow? I believe the current design can support both scenarios.

Copy link
Contributor

@tnull tnull Apr 24, 2024

Choose a reason for hiding this comment

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

I think you're talking about a model where each JIT-channel has a specific fee, defined when the channel is bought? And then this fee is slowly paid using lightning/blips#25 as HTLCs come in, and may be spread across multiple future HTLCs (in case the first HTLCs relayed are smaller than the fee)? And once the fee is fully paid, the channel seller stops claiming some of the HTLC amount they relay to the buyer? If that's the kind of flow you're discussing, then you're right, both sides need to know at channel or splice creation time the exact fee that is owed by the buyer to the seller. That's easily done though? And then each side needs to keep track of how much of that fee has already been paid, which should be simple enough as well?

Yes, this is essentially the LSPS2 or (previously proposed) LSPS4 model, where all opening fee parameters are agreed upon beforehand and the LSP even commits to them via the promise field (see https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2#1-api-information). This has the benefit that it can withhold broadcasting the funding transaction until the client claimed sufficient HTLCs/payment parts to cover the opening fee (in the 'client-trusts-LSP' trust model). On the other hand the client can protect itself against abuse as it can actually check the LSP doesn't withhold more than the agreed upon amount. Note that in LSPS2 this isn't meant to be an ongoing process, but is mostly finished once the channel is opened, and we don't prescribe what the LSP should do after the channel reaches the agreed upon min_lifetime.

I think you're right that this model should still at least be easily implemented for the basic_funding_lease type, but might of course not work with any type we may introduce in the future if we don't clearly define how the fee can be calculated upfront.

So we could end up in a scenario where we define a number of different lease types in the BOLTs here, and only a subset of them would be feasible to use with a JIT variant defined in BLIPs.
But, that might be fine (?), I mainly wanted to bring it up so we're aware of this limitation.

The model I'm discussing is different. We can imagine a wallet that tells its users "You'll pay a 1% fee on every payment you receive, and nothing else, and liquidity will be handled for you automatically". In that case there isn't a specific fee associated to each funding amount.

Right, IIUC, this is the trivial case of 0 upfront fee (making any upfront calculation unnecessary^^).

I think we want to be able to support both scenarios, right? So we should be very liberal in what we allow? I believe the current design can support both scenarios.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've spent more time trying to specify how payment for the funding liquidity could be done using HTLCs, and I slightly reworked the liquidity ads format to include a dedicated payment_type field in 45f6906.

I think this is similar to what you probably had in mind, and I believe this separation of concern between the lease type and the payment type makes sense. I'm working on the on-the-fly funding bLIP that will detail how different payment_types can be introduced (independently of the chosen lease_type).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Where the buyer doesn't pay any fee when the channel is created

One current limitation with channel buys using liquidity ads is that the buyer initiates the channel open, which means they're also responsible for the onchain closure fees. So the buyer has to contribute at least some funds to the channel at start in order for it to be operational (some CLN users have run into problems where they created basically unusable channels because they didn't put enough sats in at start for a liquidity buy)

If a buyer doesn't have any sats to begin with, they won't be able to use liqudity ad buys.

One way to solve this would be to add a flag that allows for flipping which node is considered the "opener" for the calculation of closing fees. This would put the cost/risk of channel closure onto the liquidity seller, and allows for an opener to essentially do a zero-funds (no utxo) channel open. I'd presume that the seller could price this option independently (maybe add it as a new type of lease?) as it does add a potential cost risk to them.

When you pair this with the JIT/HTLC payment plan bLIP proposals, I think you end up with a pretty nice protocol for allowing zero-UTXO parties to buy inbound liquidity at will. Maybe I'm out of date on the cost models for onchain fees in commitment transactions though?

Copy link
Collaborator Author

@t-bast t-bast May 21, 2024

Choose a reason for hiding this comment

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

One current limitation with channel buys using liquidity ads is that the buyer initiates the channel open, which means they're also responsible for the onchain closure fees. So the buyer has to contribute at least some funds to the channel at start in order for it to be operational (some CLN users have run into problems where they created basically unusable channels because they didn't put enough sats in at start for a liquidity buy)

Indeed, that's why I've been experimenting with ACINQ/eclair#2845 as a short-term solution until we move to 0-fee commit txs thanks to v3 transactions. I planned to make that option a bLIP if we want to ship before v3 transactions.

Note that once we have option_simple_close, the mutual close case isn't an issue.

02-peer-protocol.md Outdated Show resolved Hide resolved
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

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

Did a first pass, found just a few nits and questions so far.

I also like the extensible model, but have yet to spend more time thinking about the details regarding how this would work in a JIT flow exactly.

02-peer-protocol.md Outdated Show resolved Hide resolved
02-peer-protocol.md Show resolved Hide resolved
07-routing-gossip.md Outdated Show resolved Hide resolved
07-routing-gossip.md Outdated Show resolved Hide resolved
07-routing-gossip.md Outdated Show resolved Hide resolved
fees to the seller for the funding they provide to the channel based on the
agreed upon `funding_lease_fee`.

The lease fee is taken from the buyer's funding inputs and added to the
Copy link
Contributor

Choose a reason for hiding this comment

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

It seem that currently we require all lease types to incorporate funding_lease_fee as otherwise the client wouldn't be able to calculate the fee in advance, allowing it to decide whether to accept or reject an incoming HTLC from which the seller withheld an amount through lightning/blips#25.

I wonder if we're fine with this, or if it will be too inflexible going forward. Should we rather clarify that for each lease type the fee calculation needs to be spec'd too?

Add the ability to advertise rates at which nodes wish to sell their
liquidity. Buyers can then connect to sellers and request liquidity,
at one of the advertised rates.

This can be used when creating a dual-funded channel, where both
participants contribute to the funding transaction, and one of them
is paid for (some of) their contribution. This can also be used to
splice additional liquidity into existing channels, when splicing is
supported.

We support multiple types of liquidity leases, and use an extensible
format to allow adding new types of leases in the future. This can be
useful to allow different ways of paying the lease fees, and different
constraints on the seller or buyer side.

The existing lease types don't add any constraints to the commitment
transactions. The lease duration isn't protected by script opcodes,
which means that the seller could immediately close the channel, or
splice funds out. It is up to the buyer to then blacklist that seller.

We can in the future modify the commitment transactions to restrict the
seller: that can be done by introducing a new `lease_type` if it is
considered useful.
It makes more sense to start with only the most basic liquidity ads type
and add more `lease_type`s in the future, as needed.

It may be useful to readers to see how different lease types can be
introduced. The previous commit is a good example of that.
t-bast added a commit to ACINQ/eclair that referenced this pull request May 14, 2024
Add types and codecs for the extensible liquidity ads format proposed
in lightning/bolts#1153.
t-bast added a commit to ACINQ/eclair that referenced this pull request May 14, 2024
The last commit of lightning/bolts#1153
introduces a separate `payment_type` field, that allows extending the
ways fees can be paid.
The previous commits assumed that paying the liquidity fees in a
different way than during the `interactive-tx` session would be
introduced by creating a new `lease_type`. However, it turns out
that in most cases, how the fees are paid is not correlated to the
`lease_type`. We thus introduce a dedicated type for payment options.

We only define one `payment_type`, where the fees are paid from the
buyer's channel balance during the `interactive-tx` session, but it
is easy to introduce different `payment_type`s that reuse the existing
lease type but pay the fees using pending HTLCs for example.
Copy link
Collaborator

@niftynei niftynei left a comment

Choose a reason for hiding this comment

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

While this is a considerable evolution of the original proposal, I think it's fair to ask that that I get at least a by-line credit the commit description for this. For example something like

Credit to: @niftynei for the original liquidity ads proposal

02-peer-protocol.md Outdated Show resolved Hide resolved
fees to the seller for the funding they provide to the channel based on the
agreed upon `funding_lease_fee`.

The lease fee is taken from the buyer's funding inputs and added to the
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where the buyer doesn't pay any fee when the channel is created

One current limitation with channel buys using liquidity ads is that the buyer initiates the channel open, which means they're also responsible for the onchain closure fees. So the buyer has to contribute at least some funds to the channel at start in order for it to be operational (some CLN users have run into problems where they created basically unusable channels because they didn't put enough sats in at start for a liquidity buy)

If a buyer doesn't have any sats to begin with, they won't be able to use liqudity ad buys.

One way to solve this would be to add a flag that allows for flipping which node is considered the "opener" for the calculation of closing fees. This would put the cost/risk of channel closure onto the liquidity seller, and allows for an opener to essentially do a zero-funds (no utxo) channel open. I'd presume that the seller could price this option independently (maybe add it as a new type of lease?) as it does add a potential cost risk to them.

When you pair this with the JIT/HTLC payment plan bLIP proposals, I think you end up with a pretty nice protocol for allowing zero-UTXO parties to buy inbound liquidity at will. Maybe I'm out of date on the cost models for onchain fees in commitment transactions though?

@t-bast
Copy link
Collaborator Author

t-bast commented May 21, 2024

While this is a considerable evolution of the original proposal, I think it's fair to ask that that I get at least a by-line credit the commit description for this. For example something like

Of course, I'd like to re-arrange the commits once reviewed (the first commit is only here to help guide the review and shouldn't be included on master IMO), once we get closer to a final version I'll clean-up the commits and add credits!

t-bast added a commit to ACINQ/lightning-kmp that referenced this pull request May 24, 2024
We previously only used liquidity ads with splicing: we now support it
during the initial channel opening flow as well. This lets us add more
unit tests, including tests for the case where the node receiving the
`open_channel` message is responsible for paying the commitment fees.

We also update liquidity ads to use the latest version of the spec from
lightning/bolts#1153. This introduces more ways
of paying the liquidity fees, to support on-the-fly funding without
existing channel balance (not implemented in this commit).

Note that we need some backwards-compatibility with the previous
liquidity ads types in our state serialization code: when we're in the
middle of signing a splice transaction, we may have a legacy liquidity
lease in our splice status. We ignore it when finalizing the splice: the
only consequence is that we won't store an entry in our DB for that
lease, but the channel will otherwise work correctly.
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.

None yet

4 participants