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 #1153

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 01-messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,18 @@ The `features` field MUST be padded to bytes with 0s.
1. type: 3 (`remote_addr`)
2. data:
* [`...*byte`:`data`]
1. type: 5 (`option_will_fund`)
2. data:
* [`will_fund_rates`:`will_fund_rates`]

The optional `networks` indicates the chains the node is interested in.

The optional `remote_addr` can be used to circumvent NAT issues.

`option_will_fund` allows nodes to announce their willingness to provide funding
to other nodes using one of the included funding rates, as described in the
[liquidity ads section](07-routing-gossip.md#liquidity-ads).

#### Requirements

The sending node:
Expand Down
58 changes: 58 additions & 0 deletions 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,9 @@ completed.
2. data:
* [`s64`:`satoshis`]
1. type: 2 (`require_confirmed_inputs`)
1. type: 5 (`request_funding`)
2. data:
* [`request_funds`:`request_funds`]

#### Requirements

Expand All @@ -463,6 +466,12 @@ The sender:
- MUST set `funding_output_contribution`
- If it requires the receiving node to only use confirmed inputs:
- MUST set `require_confirmed_inputs`
- If it wants the receiving node to contribute to the funding transaction
using `option_will_fund`:
- MUST send `request_funding` containing one of the funding rates and
`payment_type`s supported by the receiving node.
- If the previous transaction included `request_funding`:
- SHOULD include `request_funding`.

The recipient:
- MUST respond either with `tx_abort` or with `tx_ack_rbf`
Expand All @@ -472,6 +481,8 @@ The recipient:
- MAY send `tx_abort` for any reason
- MUST fail the negotiation if:
- `require_confirmed_inputs` is set but it cannot provide confirmed inputs
- `request_funding` was included in the previous transaction but is not
included in `tx_init_rbf`.

#### Rationale

Expand Down Expand Up @@ -505,6 +516,9 @@ not contributing to the funding output.
2. data:
* [`s64`:`satoshis`]
1. type: 2 (`require_confirmed_inputs`)
1. type: 5 (`provide_funding`)
2. data:
* [`will_fund`:`will_fund`]

#### Requirements

Expand All @@ -513,12 +527,16 @@ The sender:
- MUST set `funding_output_contribution`
- If it requires the receiving node to only use confirmed inputs:
- MUST set `require_confirmed_inputs`
- If the `request_funding` TLV was sent in `tx_init_rbf`:
- MUST apply the same requirements as `accept_channel2`

The recipient:
- MUST respond with `tx_abort` or with a `tx_add_input` message,
restarting the interactive tx collaboration protocol.
- MUST fail the negotiation if:
- `require_confirmed_inputs` is set but it cannot provide confirmed inputs
- MAY fail the negotiation if `provide_funding` does not match what it
expects, similar to the requirements for `accept_channel2`.

#### Rationale

Expand Down Expand Up @@ -1163,6 +1181,9 @@ This message initiates the v2 channel establishment workflow.
2. data:
* [`...*byte`:`type`]
1. type: 2 (`require_confirmed_inputs`)
1. type: 5 (`request_funding`)
2. data:
* [`request_funds`:`request_funds`]

Rationale and Requirements are the same as for [`open_channel`](#the-open_channel-message),
with the following additions.
Expand All @@ -1177,11 +1198,18 @@ The sending node:
- MUST set `funding_feerate_perkw` to the feerate for this transaction
- If it requires the receiving node to only use confirmed inputs:
- MUST set `require_confirmed_inputs`
- If it wants the receiving node to contribute to the funding transaction
using `option_will_fund`:
- MUST send `request_funding` containing one of the funding rates and
`payment_type`s supported by the receiving node.
- MUST set `requested_sats` to the amount of sats it wants to pay for at
the advertised funding rate.

The receiving node:
- MAY fail the negotiation if:
- the `locktime` is unacceptable
- the `funding_feerate_perkw` is unacceptable
- `request_funds.funding_rate` does not match a rate it advertised.
- MUST fail the negotiation if:
- `require_confirmed_inputs` is set but it cannot provide confirmed inputs

Expand Down Expand Up @@ -1250,6 +1278,9 @@ acceptance of the new channel.
2. data:
* [`...*byte`:`type`]
1. type: 2 (`require_confirmed_inputs`)
1. type: 5 (`provide_funding`)
2. data:
* [`will_fund`:`will_fund`]

Rationale and Requirements are the same as listed above,
for [`accept_channel`](#the-accept_channel-message) with the following
Expand All @@ -1262,10 +1293,29 @@ The accepting node:
- MAY respond with a `funding_satoshis` value of zero.
- If it requires the opening node to only use confirmed inputs:
- MUST set `require_confirmed_inputs`
- If the `request_funding` TLV was sent in `open_channel2`:
- If it does not want to contribute funds or to be paid for its
funding contributions:
- SHOULD omit the `provide_funding` TLV.
- Otherwise, if it decides to be paid for its contributions:
- MUST include the `provide_funding` TLV.
- MUST set `funding_satoshis` to a value greater than `0`.
- MAY set `funding_satoshis` less or more than `requested_sats`.

The receiving node:
- MAY fail the negotiation if:
- It sent `request_funding` and `provide_funding` is not set.
- It sent `request_funding` and `provide_funding` is set and:
t-bast marked this conversation as resolved.
Show resolved Hide resolved
- `funding_satoshis` is smaller than requested.
- MUST fail the negotiation if:
- `require_confirmed_inputs` is set but it cannot provide confirmed inputs
- `provide_funding` is set but `request_funding` was not sent in `open_channel2`.
- `provide_funding` is set and:
- `will_fund.funding_rate` does not match `request_funds.funding_rate`.
- `will_fund.funding_script` does not match the channel funding script.
- `will_fund.signature` is invalid.
- MUST pay fees for the `option_will_fund` amount using the `payment_type` selected,
as detailed in the [liquidity ads section](07-routing-gossip.md#liquidity-ads).

#### Rationale

Expand All @@ -1278,6 +1328,14 @@ Instead, the channel reserve is fixed at 1% of the total channel balance
rounded down to the nearest whole satoshi or the `dust_limit_satoshis`,
whichever is greater.

If the opener sent `request_funding` in their `open_channel2` message, the
accepter node may choose to contribute funds, but they don't have to.

If the accepter node has run out of available funds, they should either fail
the negotiation or reply with a `funding_satoshis` set to `0` and omit the
`provide_funding` TLV, allowing the opener to decide whether they want to
proceed anyway or fail the negotiation.

### Funding Composition

Funding composition for channel establishment v2 makes use of the
Expand Down
196 changes: 196 additions & 0 deletions 07-routing-gossip.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ To support channel and node discovery, three *gossip messages* are supported:
* [HTLC Fees](#htlc-fees)
* [Pruning the Network View](#pruning-the-network-view)
* [Recommendations for Routing](#recommendations-for-routing)
* [Liquidity Ads](#liquidity-ads)
* [References](#references)

## Definition of `short_channel_id`
Expand Down Expand Up @@ -269,6 +270,13 @@ nodes not associated with an already known channel are ignored.
* [`32*byte`:`alias`]
* [`u16`:`addrlen`]
* [`addrlen*byte`:`addresses`]
* [`node_announcement_tlvs`:`tlvs`]

1. `tlv_stream`: `node_announcement_tlvs`
2. types:
1. type: 5 (`option_will_fund`)
2. data:
* [`will_fund_rates`:`will_fund_rates`]

`timestamp` allows for the ordering of messages, in the case of multiple
announcements. `rgb_color` and `alias` allow intelligence services to assign
Expand All @@ -279,6 +287,10 @@ connections: it contains a series of `address descriptor`s for connecting to the
node. The first byte describes the address type and is followed by the
appropriate number of bytes for that type.

`option_will_fund` allows nodes to announce their willingness to provide funding
to other nodes using one of the included funding rates, as described in the
[liquidity ads section](#liquidity-ads).

The following `address descriptor` types are defined:

* `1`: ipv4; data = `[4:ipv4_addr][2:port]` (length 6)
Expand Down Expand Up @@ -322,6 +334,9 @@ The origin node:
bits it sets.
- SHOULD not announce a Tor v2 onion service.
- MUST NOT announce more than one `type 5` DNS hostname.
- If it includes `option_will_fund`:
- MAY include multiple funding rates.
- SHOULD NOT include more than 10 funding rates.

The receiving node:
- if `node_id` is NOT a valid compressed public key:
Expand Down Expand Up @@ -1107,6 +1122,187 @@ A->D's `update_add_htlc` message would be:
And D->C's `update_add_htlc` would again be the same as B->C's direct payment
above.

## Liquidity Ads

Liquidity ads allow nodes to announce their willingness to provide funding to
other nodes for a fee. Sellers advertise various rates for the liquidity they
are selling.

1. subtype: `funding_rate`
2. data:
* [`u32`:`min_funding_amount_sat`]
* [`u32`:`max_funding_amount_sat`]
* [`u16`:`funding_weight`]
* [`u16`:`funding_fee_basis`]
* [`u32`:`funding_fee_base_sat`]
* [`u32`:`channel_creation_fee_sat`]

Sellers also define how the fees can be paid by listing the `payment_type`s
they support.

1. `payment_type`: 0 (`from_channel_balance`)

Payment types are encoded using the TLV format, using the `payment_type` for
the type field.

Sellers advertize their rates and payment types using `will_fund_rates`.

1. subtype: `will_fund_rates`
2. data:
* [`u16`:`funding_rates_count`]
* [`funding_rates_count*funding_rate`:`funding_rates`]
* [`u16`:`payment_types_len`]
* [`payment_types_len*byte`:`payment_types`]

Buyers select a specific rate and a `payment_type` offered by the seller
and use `request_funds` to purchase that liquidity.

1. subtype: `request_funds`
2. data:
* [`u64`:`requested_sats`]
* [`funding_rate`:`funding_rate`]
* [`payment_type`:`payment_type`]

Sellers accept the purchase with `will_fund` containing a signature that
commits to the liquidity purchase parameters.

1. subtype: `will_fund`
2. data:
* [`funding_rate`:`funding_rate`]
* [`u16`:`funding_script_len`]
* [`funding_script_len*byte`:`funding_script`]
* [`signature`:`signature`]

### Requirements

A node selling liquidity:
- MUST advertise its funding rates with `will_fund_rates`:
- MUST include a list of `funding_rate`s for the amounts it may provide.
- MUST include a `payment_types` bitfield: for each `payment_type` that
it supports, the bit at the position matching this type MUST be set.
- When receiving `request_funds`:
- If the `funding_rate` does not match a rate it offers:
- MUST reject the funding attempt.
- If the `payment_type` is not supported:
- MUST reject the funding attempt.
- Otherwise:
- MUST send `will_fund` with the received `funding_rate`, the funding
script and a signature covering those fields (see below).
- MUST keep the channel open for at least a month to honor the
liquidity purchase.

A node buying liquidity:
- MUST ignore any unknown `payment_type` in `will_fund_rates.payment_types`.
- MUST create `request_funds` with a `funding_rate` from the `funding_rates`
and a `payment_type` from the `payment_types` bitfield.
- MUST encode `payment_type` using the TLV format.

### Computing liquidity fees

When `request_funds` and `will_fund` have been exchanged, the buyer agrees to
pay fees to the seller for the funding they provide to the channel based on
the proposed `funding_weight`, `funding_fee_basis` and `funding_fee_base_sat`.

If the buyer is opening a new channel, an additional `channel_creation_fee_sat`
is applied. This can be used to hedge some of the future cost of closing that
channel, which doesn't apply when additional liquidity is purchased on an
existing channel (since the creation fee has already been paid).

The funding fee has three components:

* a fixed amount:
* `funding_fee_base_sat` if liquidity is purchased on an existing channel
* `funding_fee_base_sat + channel_creation_fee_sat` when opening a channel
* a proportional amount based on the seller's `funding_amount`:
* `paid_funding_contribution = min(funding_amount, request_funds.requested_sats)`
* `funding_fee_proportional_sat = paid_funding_contribution * funding_fee_basis / 10_000`
* a contribution to the on-chain fees paid by the seller:
* `funding_fee_mining_sat = funding_weight * funding_feerate_perkw / 1000`

The total fee for a channel creation is then:

funding_fee_total = funding_fee_base_sat + channel_creation_fee_sat + funding_fee_proportional_sat + funding_fee_mining_sat

The total fee for buying liquidity on an existing channel is:

funding_fee_total = funding_fee_base_sat + funding_fee_proportional_sat + funding_fee_mining_sat

The seller provides an ECDSA signature in `will_fund` using the private key
associated with their `node_id`. The data signed is:

SHA256("liquidity_ads_purchase" || funding_rate || funding_script)

We use a tagged hash to ensure that this signature cannot be used in a
different context.

#### Requirements

A node advertising a `funding_rate`:
- MUST set `min_funding_amount_sat` and `max_funding_amount_sat` to the
minimum and maximum amount it will contribute at this rate.
- MUST set `funding_fee_base_sat` to the base fee (in satoshi) it will charge.
- MUST set `channel_creation_fee_sat` to the additional fee it will charge for
channel creation.
- MUST set `funding_fee_basis` to the amount it will charge per contributed
satoshi (in basis points, ie 1/10_000).
- MUST set `funding_weight` to the transaction weight that will be charged.
It ensures that the funding node is refunded for some of the on-chain
fees it will pay to contribute the requested funds to a channel.

### The `from_channel_balance` payment type

The funding fee is taken from the buyer's transaction inputs and added to the
seller's channel balance during the funding flow, using the
[interactive-tx](./02-peer-protocol.md#interactive-transaction-construction)
protocol. The buyer must contribute enough funds to cover their channel
balance, the funding fee, and the on-chain fees for the weight of the funding
transaction they're responsible for.

#### Example

A node contributes `500_000 sats` to a channel and requests `1_000_000 sats`
from its peer, at a feerate of `2500 sat/kw`. The total weight of their inputs
and outputs in the funding transaction is 720. More details about transaction
weight can be found in the [interactive-tx section](02-peer-protocol.md#interactive-transaction-construction).

The seller contributes `1_100_000 sats` with the following funding rate:

funding_weight = 444
funding_fee_base_sat = 233 sats
channel_creation_fee_sat = 500 sats
funding_fee_basis = 22

The funding fee is:

funding_fee_base_sat = 233 sats
channel_creation_fee_sat = 500 sats
funding_fee_proportional_sat = min(1_000_000, 1_100_000) * 22 / 10_000 = 2200 sats
funding_fee_mining_sat = 444 * 2500 / 1000 = 1110 sats
funding_fee_total = 4043 sats

The outputs to the peers in the commitment transaction will be

to-buyer: 500_000 sats
to-seller: 1_104_043 sats

The miner fee for the buyer will be `720 * 2500 / 1000 = 1800 sats`.

Minimum funds that the buyer must contribute to the funding transaction:

open_channel2.funding_satoshis: 500_000 sats
funding fee: 4_043 sats
miner fee: 1_800 sats
total required contribution: 505_843 sats

Minimum funds that the seller must contribute to the funding transaction:

accept_channel2.funding_satoshis: 1_100_000 sats
miner fee [1]: 1_110 sats
total required contribution: 1_101_110 sats

[1] assumes `funding_weight = 444` is their total weight for this transaction.

## References

![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png "License CC-BY")
<br>
Expand Down
Loading