diff --git a/01-messaging.md b/01-messaging.md index 67ca9e370..71e82d6b3 100644 --- a/01-messaging.md +++ b/01-messaging.md @@ -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: diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 27b01fe04..1bd621166 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -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 @@ -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` @@ -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 @@ -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 @@ -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 @@ -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. @@ -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 @@ -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 @@ -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: + - `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 @@ -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 diff --git a/07-routing-gossip.md b/07-routing-gossip.md index 22353278c..991360ea7 100644 --- a/07-routing-gossip.md +++ b/07-routing-gossip.md @@ -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` @@ -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 @@ -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) @@ -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: @@ -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")
diff --git a/bolt07/liquidity-ads.json b/bolt07/liquidity-ads.json new file mode 100644 index 000000000..742777e94 --- /dev/null +++ b/bolt07/liquidity-ads.json @@ -0,0 +1,122 @@ +{ + "node_private_key": "57ac961f1b80ebfb610037bf9c96c6333699bde42257919a53974811c34649e3", + "node_announcement": { + "node_id": "03ca9b880627d2d4e3b33164f66946349f820d26aa9572fe0e525e534850cbd413", + "alias": "LN-liquidity", + "features": [], + "color": [ + 42, + 117, + 87 + ], + "addresses": [], + "timestamp": 1713171401, + "tlvStream": { + "option_will_fund": { + "funding_rates": [ + { + "min_funding_amount_sat": 100000, + "max_funding_amount_sat": 500000, + "funding_weight": 550, + "funding_fee_basis": 100, + "funding_fee_base_sat": 5000, + "channel_creation_fee_sat": 1000, + "encoded": "000186a0 0007a120 0226 0064 00001388 000003e8" + }, + { + "min_funding_amount_sat": 500000, + "max_funding_amount_sat": 5000000, + "funding_weight": 1100, + "funding_fee_basis": 75, + "funding_fee_base_sat": 0, + "channel_creation_fee_sat": 1500, + "encoded": "0007a120 004c4b40 044c 004b 00000000 000005dc" + } + ], + "payment_types": { + "supported": [ + "from_channel_balance" + ], + "encoded": "01" + } + } + }, + "signature": "2e6a9b7017d0c6d8c823f6aa5fcaaea266ea5c7ebc88345efc3ec227e71dee38148371cef4ffaf6d37318de42ded99203e89aaf9f697ad211915dc83dc9cfa63", + "encoded": "0101 2e6a9b7017d0c6d8c823f6aa5fcaaea266ea5c7ebc88345efc3ec227e71dee38148371cef4ffaf6d37318de42ded99203e89aaf9f697ad211915dc83dc9cfa63 0000 661cebc9 03ca9b880627d2d4e3b33164f66946349f820d26aa9572fe0e525e534850cbd413 2a7557 4c4e2d4c69717569646974790000000000000000000000000000000000000000 0000 052d0002000186a00007a1200226006400001388000003e80007a120004c4b40044c004b00000000000005dc000101" + }, + "open_channel2": { + "chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + "temporaryChannelId": "0100000000000000000000000000000000000000000000000000000000000000", + "fundingFeerate": 5000, + "commitmentFeerate": 4000, + "fundingAmount": 250000, + "dustLimit": 500, + "maxHtlcValueInFlightMsat": 50000, + "htlcMinimum": 15, + "toSelfDelay": 144, + "maxAcceptedHtlcs": 483, + "lockTime": 650000, + "fundingPubkey": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "revocationBasepoint": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "paymentBasepoint": "02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337", + "delayedPaymentBasepoint": "03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b", + "htlcBasepoint": "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7", + "firstPerCommitmentPoint": "03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a", + "secondPerCommitmentPoint": "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f", + "channelFlags": { + "announceChannel": true + }, + "tlvStream": { + "request_funding": { + "requested_sats": 750000, + "funding_rate": { + "min_funding_amount_sat": 500000, + "max_funding_amount_sat": 5000000, + "funding_weight": 1100, + "funding_fee_basis": 75, + "funding_fee_base_sat": 0, + "channel_creation_fee_sat": 1500 + }, + "payment_type": { + "type": "from_channel_balance", + "encoded": "0000" + }, + "encoded": "05 1e 00000000000b71b0 0007a120004c4b40044c004b00000000000005dc 0000" + } + }, + "encoded": "0040 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 0100000000000000000000000000000000000000000000000000000000000000 00001388 00000fa0 000000000003d090 00000000000001f4 000000000000c350 000000000000000f 0090 01e3 0009eb10 031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f 024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766 02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337 03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b 0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7 03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a 02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f 01 051e00000000000b71b00007a120004c4b40044c004b00000000000005dc0000" + }, + "accept_channel2": { + "temporaryChannelId": "0100000000000000000000000000000000000000000000000000000000000000", + "fundingAmount": 700000, + "dustLimit": 473, + "maxHtlcValueInFlightMsat": 100000000, + "htlcMinimum": 1, + "minimumDepth": 6, + "toSelfDelay": 144, + "maxAcceptedHtlcs": 50, + "fundingPubkey": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + "revocationBasepoint": "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + "paymentBasepoint": "02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337", + "delayedPaymentBasepoint": "03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b", + "htlcBasepoint": "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7", + "firstPerCommitmentPoint": "03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a", + "secondPerCommitmentPoint": "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f", + "tlvStream": { + "provide_funding": { + "funding_rate": { + "min_funding_amount_sat": 500000, + "max_funding_amount_sat": 5000000, + "funding_weight": 1100, + "funding_fee_basis": 75, + "funding_fee_base_sat": 0, + "channel_creation_fee_sat": 1500 + }, + "funding_script": "00202ec38203f4cf37a3b377d9a55c7ae0153c643046dbdbe2ffccfb11b74420103c", + "signature": "c57cf393f6bd534472ec08cbfbbc7268501b32f563a21cdf02a99127c4f25168249acd6509f96b2e93843c3b838ee4808c75d0a15ff71ba886fda980b8ca954f", + "encoded": "05 78 0007a120004c4b40044c004b00000000000005dc 002200202ec38203f4cf37a3b377d9a55c7ae0153c643046dbdbe2ffccfb11b74420103c c57cf393f6bd534472ec08cbfbbc7268501b32f563a21cdf02a99127c4f25168249acd6509f96b2e93843c3b838ee4808c75d0a15ff71ba886fda980b8ca954f" + } + }, + "encoded": "0041 0100000000000000000000000000000000000000000000000000000000000000 00000000000aae60 00000000000001d9 0000000005f5e100 0000000000000001 00000006 0090 0032 031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f 024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766 02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337 03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b 0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7 03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a 02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f 05780007a120004c4b40044c004b00000000000005dc002200202ec38203f4cf37a3b377d9a55c7ae0153c643046dbdbe2ffccfb11b74420103cc57cf393f6bd534472ec08cbfbbc7268501b32f563a21cdf02a99127c4f25168249acd6509f96b2e93843c3b838ee4808c75d0a15ff71ba886fda980b8ca954f" + } +} \ No newline at end of file