Skip to content

Commit

Permalink
LSPS1: Explicitly support LSPS1 payment options
Browse files Browse the repository at this point in the history
This PR aims to address a few problems in LSPS1.
I'll provide a few motivating examples of why I believe
the changes proposed in this MR are desirable.

# 1. Use seprate fee for onchain vs lightning payment

Onchain payments are more expensive for the LSP than lightning payments
because they create their own utxo. The LSP will have to carry the cost
of spending that new utxo at a later point in time.

This PR provides LSP's the option to set a different fee depending
on the payment method.

On a related note @2Fast2BCn [noted](BitcoinAndLightningLayerSpecs#95 (comment))
that a similar argument could be made for the `expiry_date` of an order.
The LSP might want to set a different `expiry_date` depending on the
chosen payment option.

See issue: BitcoinAndLightningLayerSpecs#92
See comment: BitcoinAndLightningLayerSpecs#95 (comment)

# 2. Extensibility for additional payment methods

This PR allows to add additional payment options later.

In this section I'll provide a few motivating example.

## 2.1. Dual funding

Recently, dual-funding got merged to the spec. The spec describes a new
channel open protocol in which both the client and server can contribute
funds.

This approach provides a superior trust model. The client doesn't have
to trust the LSP to open the channel. The benefit is especially clear if
`client_balance_sat` is high. In the current version of LSPS1 the LSP
could take the money and run.

## 2.2. BOLT-12 support

Today, BOLT-11 invoices are commonly used to make payments over
lightning. Personally, I'd describe myself as a BOLT-12 maxi. This PR
makes it easier to add BOLT-12 as a payment option later.

### 2.3 Withhold from first payment

We see a demand for JIT-channels where the client specifies the
channel-size. This is currently not possible on LSPS2 or LSPS4.

See issue: BitcoinAndLightningLayerSpecs#65

# Breaking changes: Why (not) to merge this MR?

We are in a bit of tension here. The spec is marked as
`FOR IMPLEMENTATION` but we are seeing some usage on mainnet.

This PR is breaking in the sense that clients will not be able to
purchase channel if either the client or server uses this new revision.

However, there will be some hassle for users but merging
this MR should not put any funds at risk.
  • Loading branch information
ErikDeSmedt committed Mar 4, 2024
1 parent 2177b4d commit 9beaa9a
Showing 1 changed file with 83 additions and 52 deletions.
135 changes: 83 additions & 52 deletions LSPS1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ The client MUST call `lsps1.get_info` first.
"min_channel_confirmations": 0,
"min_onchain_payment_confirmations": null,
"supports_zero_channel_reserve": true,
"min_onchain_payment_size_sat": null,
"max_channel_expiry_blocks": 20160,
"min_initial_client_balance_sat": "20000",
"max_initial_client_balance_sat": "100000000",
Expand All @@ -98,12 +97,10 @@ The client MUST call `lsps1.get_info` first.
- `min_onchain_payment_confirmations <uint8>` Minimum number of block confirmations before the LSP accepts an on-chain payment as confirmed. This is a lower bound. The LSP MAY increase this value by responding with a different value in `lsps1.create_order.min_onchain_payment_confirmations ` depending on the size of the channels and risk management.
- MAY be 0 to allow 0conf payments.
- MUST be 0 or greater.
- MAY be `null` if on-chain payments are NOT supported.
- MAY be `null` or omitted if on-chain payments are NOT supported.
- `supports_onchain_payments` <boolean> True if the LSP supports [onchain payments](#### 3.2 Onchain payments).
- May be omitted if the LSP does not support onchain payments.
- `supports_zero_channel_reserve <boolean>` Indicates if the LSP supports [zeroreserve](https://github.com/ElementsProject/lightning/pull/5315).
- `min_onchain_payment_size_sat` <[LSPS0.sat][] or `null`> Indicates the minimum amount of satoshi (`order_total_sat`) that is required for the LSP to accept a payment on-chain.
- The LSP MUST allow on-chain payments equal or above this value.
- MUST be 0 or greater.
- MAY be `null` if on-chain payments are NOT supported.
- `max_channel_expiry_blocks <uint32>` The maximum number of blocks a channel can be leased for.
- MUST be 1 or greater.
- `min_initial_client_balance_sat` <[LSPS0.sat][]> Minimum number of satoshi that the client MUST request.
Expand All @@ -119,6 +116,7 @@ The client MUST call `lsps1.get_info` first.
- `max_channel_balance_sat` <[LSPS0.sat][]> Maximum channel size.
- MUST be 0 or greater.


Every `min/max` options pair MUST ensure that `min <= max`.

**Errors** No additional errors are defined for this method.
Expand Down Expand Up @@ -185,17 +183,19 @@ The client MUST check if [option_support_large_channel](https://bitcoinops.org/e
"channel_expiry_blocks": 12,
"token": "",
"created_at": "2012-04-23T18:25:43.511Z",
"expires_at": "2015-01-25T19:29:44.612Z",
"announce_channel": true,
"order_state": "CREATED",
"payment": {
"lightning": {
"bolt11": {
"state": "EXPECT_PAYMENT",
"fee_total_sat": 8888,
"order_total_sat: 2008888,
"expires_at": "2015-01-25T19:29:44.612Z",
"invoice" : "lnbc252u1p3aht9ysp580g4633gd2x9lc5al0wd8wx0mpn9748jeyz46kqjrpxn52uhfpjqpp5qgf67tcqmuqehzgjm8mzya90h73deafvr4m5705l5u5l4r05l8cqdpud3h8ymm4w3jhytnpwpczqmt0de6xsmre2pkxzm3qydmkzdjrdev9s7zhgfaqxqyjw5qcqpjrzjqt6xptnd85lpqnu2lefq4cx070v5cdwzh2xlvmdgnu7gqp4zvkus5zapryqqx9qqqyqqqqqqqqqqqcsq9q9qyysgqen77vu8xqjelum24hgjpgfdgfgx4q0nehhalcmuggt32japhjuksq9jv6eksjfnppm4hrzsgyxt8y8xacxut9qv3fpyetz8t7tsymygq8yzn05"},
"onchain": {
"fee_total_sat": 9999,
"order_total_sat": 2009999,
"expires_at": "2015-01-25T19:29:44.612Z",
"address" : "bc1p5uvtaxzkjwvey2tfy49k5vtqfpjmrgm09cvs88ezyy8h2zv7jhas9tu4y",
"min_fee_for_0conf": 253,
"min_onchain_payment_confirmations": 0}
Expand All @@ -216,7 +216,6 @@ The client MUST check if [option_support_large_channel](https://bitcoinops.org/e
- MUST be an empty string if the token was not provided.
- `announce_channel <boolean>` Mirrored from the request.
- `created_at` <[LSPS0.datetime][]> Datetime when the order was created.
- `expires_at` <[LSPS0.datetime][]> Datetime when the order expires.
- `order_state <string enum>` Current state of the order.
- `CREATED` Order has been created. Default value.
- `COMPLETED` LSP has published funding transaction.
Expand Down Expand Up @@ -285,19 +284,78 @@ The client MAY check the current status of the order at any point.

### 3. Payment

This section describes the `payment` object returned by `lsps1.create_order` and `lsps1.get_order`. The client MUST pay the `bolt11_invoice` OR the `onchain_address`. Using both methods MAY lead to the loss of funds.
This section describes the `payment` object returned by `lsps1.create_order` and `lsps1.get_order`.

```json
"payment": {
"onchain": {...}.
"bolt11": {...}
}
```

An LSP MAY omit payment options.
> **Rationale**: E.g: The LSP might not support onchain payments.
> **Rationale** On-chain payments are required for payments with higher amounts, especially to push `client_balance_sat` to the client. On-chain payments are also useful to onboard new users to Lightining. On the other hand, Lightning payments are the preferred way to do payments because they are quick and easily refundable.
> **Rationale**:
> Fees and expiry dates are defined on the level of the payment-option.
> This allows an LSP to provide the cheapest service for each payment option.
>
> An LSP might choose to have a lower fee for lightning than for onchain payments.
> Onchain payments might
> - be more costly for the LSP as they might have to spend a small UTXO in the future
> - be more risky for the LSP in case of 0-conf channels
> - require longer confirmation times than a lightning payment. (Risk of changing on-chain fees)

**Payment object**
#### 3.1 Lightning Payments using BOLT-11

```json
"payment": {
"bolt11": {
"state" : "EXPECT_PAYMENT",
"bolt11_invoice": "lnbc252u1p3aht9ysp580g4633gd2x9lc5al0wd8wx0mpn97..."
"fee_total_sat": 8888,
"order_total_sat": "200888",
"state": "EXPECT_PAYMENT"
}
```

- `state`
- `EXPECT_PAYMENT` Payment expected.
- `HOLD` Lighting payment arrived, preimage NOT released.
- `PAID` When the has been reimage released
- `REFUNDED` Lightning payment has been refunded.
- `expires_at` <[LSPS0.datetime][]> The timestamp at which the
- `fee_total_sat` <[LSPS0.sat][]> The total fee the LSP will charge to open this channel in satoshi.
- `order_total_sat` <[LSPS0.sat][]> What the client needs to pay in total to open the requested channel.
- MUST be the `fee_total_sat` plus the `client_balance_sat` requested in satoshi.
- `bolt11_invoice <string>`
- MUST be a [Lightning BOLT 11 invoice](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) for the number of `order_total_sat`.
- Invoice MUST be a [HOLD invoice](https://bitcoinops.org/en/topics/hold-invoices/).
- MUST be at most 2048 characters long.

**Client**

- MAY pay the `bolt11_invoice`.
- MAY pull `lsps1.get_order` to check the success of the payment.
- The client gets refunded automatically in case the channel open failed, the order expires, or just before the payment times out.

**LSP**

- MUST change the `payment.state` to `HOLD` when the payment arrived.
- If the channel has been opened successfully
- MUST release the preimage and therefore complete the payment.
- MUST set the `payment.state` to `PAID`.
- If the channel failed to open or the order expired or shortly before the payment times out:
- MUST reject the payment.
- MUST set the `payment.state` to `REFUNDED`.

#### 3.2 Onchain payments

```json
"onchain": {
"state": "EXPECT_PAYMENT",
"fee_total_sat": "8888",
"order_total_sat": "2008888",
"bolt11_invoice": "lnbc252u1p3aht9ysp580g4633gd2x9lc5al0wd8wx0mpn97...",
"fee_total_sat": 9999,
"order_total_sat": 200999,
"onchain_address": "bc1p5uvtaxzkjwvey2tfy49k5vtqfpjmrgm09cvs88ezyy8h2zv7jhas9tu4yr",
"min_onchain_payment_confirmations": 1,
"min_fee_for_0conf": 253,
Expand All @@ -306,21 +364,16 @@ This section describes the `payment` object returned by `lsps1.create_order` and
"sat": "1200",
"confirmed": false
}
},
}
```

- `state <string enum>` MUST be one of these values:
- `EXPECT_PAYMENT` Payment expected.
- `HOLD` Lighting payment arrived, preimage NOT released.
- `PAID` Lightning payment arrived, preimage released OR full `order_total_sat` on-chain payment arrived.
- `REFUNDED` Lightning payment or on-chain payment has been refunded.
- `state`
- `EXPECT_PAYMENT`: Payment expected
- `PAID`: Onchain payment is confirmed
- `REFUNDED`: Onchain payment has been refunded
- `fee_total_sat` <[LSPS0.sat][]> The total fee the LSP will charge to open this channel in satoshi.
- `order_total_sat` <[LSPS0.sat][]> What the client needs to pay in total to open the requested channel.
- MUST be the `fee_total_sat` plus the `client_balance_sat` requested in satoshi.
- `bolt11_invoice <string>`
- MUST be a [Lightning BOLT 11 invoice](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) for the number of `order_total_sat`.
- Invoice MUST be a [HOLD invoice](https://bitcoinops.org/en/topics/hold-invoices/).
- MUST be at most 2048 characters long.
- MUST be the `fee_total_sat` plus the `client_balance_sat` requested in satoshi.
- `onchain_address` <[LSPS0.onchain_address][]> On-chain address the client can pay the `order_total_sat` to
- MUST be `null` IF one of the following is true:
- `options.min_onchain_payment_size_sat` is greater than `order_total_sat`.
Expand All @@ -344,28 +397,6 @@ This section describes the `payment` object returned by `lsps1.create_order` and
> **Rationale `min_fee_for_0conf`** The client MAY want to have instant confirmation of the on-chain payment. The LSP can mitigate the risk of a double spend by requiring a high fee rate. The client can then decide if he wants to pay the high fee rate or wait for the on-chain payment to be confirmed once.
#### 3.1 Lightning Payment

**Client**

- MUST pay the `bolt11_invoice`.
- SHOULD pull `lsps1.get_order` to check the success of the payment.
- The client gets refunded automatically in case the channel open failed, the order expires, or just before the payment times out.

**LSP**

- MUST change the `payment.state` to `HOLD` when the payment arrived.
- If the channel has been opened successfully
- MUST release the preimage and therefore complete the payment.
- MUST set the `payment.state` to `PAID`.
- If the channel failed to open or the order expired or shortly before the payment times out:
- MUST reject the payment.
- MUST set the `payment.state` to `REFUNDED`.



#### 3.2 Onchain Payment Flow

**Client**

- MUST pay `order_total_sat` to `onchain_address`.
Expand All @@ -377,9 +408,9 @@ This section describes the `payment` object returned by `lsps1.create_order` and
- IF `min_onchain_payment_confirmations ` is 0 and incoming transaction fee is greater than `min_fee_for_0conf`:
- SHOULD set the transaction as confirmed.
- IF `min_onchain_payment_confirmations ` is equal or greater than 1:
- SHOULD set the transaction as confirmed after `min_onchain_payment_confirmations ` confirmations.
- MAY always set the transaction as confirmed before `min_onchain_payment_confirmations ` confirmations.
- In rare circumstances, MAY take longer than `min_onchain_payment_confirmations ` confirmations in case the LSP doesn't trust the transaction.
- SHOULD set the transaction as confirmed after `min_onchain_payment_confirmations` confirmations.
- MAY always set the transaction as confirmed before `min_onchain_payment_confirmations` confirmations.
- In rare circumstances, MAY take longer than `min_onchain_payment_confirmations` confirmations in case the LSP doesn't trust the transaction.
- MUST always set the transaction as confirmed after 6 block confirmations.


Expand Down

0 comments on commit 9beaa9a

Please sign in to comment.