Skip to content

Commit

Permalink
LSPS3: JIT Channels.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZmnSCPxj-jr committed Mar 14, 2023
1 parent 0b195ee commit 0fd471c
Showing 1 changed file with 317 additions and 0 deletions.
317 changes: 317 additions & 0 deletions LSPS3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
# LSPS3 JIT Channel Negotiation

|Name | `base_api` |
|--------|--------------------------|
|Version | 1 |

## Motivation

A "JIT Channel" is a 0-conf channel opened in response to an incoming payment
from the public network to a client, via the LSP.
This allows a client with no Lightning channels to start receiving on
Lightning, and have the cost of their inbound liquidity be deducted from their
first received payment.

### Trust Models

As of this version, the trust model is that the LSP trusts clients to actually
claim their payment once the channel is opened and the payment is forwarded.

If the client does not claim the payment, and the funding transaction confirms,
then the LSP will have its funds locked in a channel that was not paid for.
Even if the LSP disables all other use of the channel until the payment paying
for the channel is claimed, the client may then refuse all mutual close attempts
in retaliation (by disconnecting), and force the LSP to unilaterally close,
which locks the funds until the `to_self_delay` (indicated by the client, and
imposed on the LSP) has passed.

LSPs that implement this API SHOULD include mitigations to allow them to
determine if clients can be trusted, or to detect and protect against attacks
on the LSP.
How those mitigations are performed is beyond the scope of this specification.

### Amounts

All amounts in this protocol are specified in millisatoshi.

All millisatoshi values MUST be represented as a string and MUST NOT be
represented as integer values.

> **Rationale** JSON numbers are specified to only fit IEEE double-precision
> numbers, which have a 53 bit mantissa.
> The maximum number of millisatoshis (21 million BTC) cannot be specified in
> 53 bits.
> In addition, actual JSON parsers may use a smaller size for parsed integers;
> for instance, as signed 32 bit numbers.
> The largest safe value is 2,147,483,647; 2,147,483,647msat = BTC0.021,474,836,47
> which is too low.
### Actors

'LSP' is the API provider.
'Client' is the API client.
'Payer' is who pays for the initial receive of the client.

## Flow (LSP Trusts Client Model)

Overview:

* The client determines that it would like to receive over Lightning, but
it has no inbound capacity, and the client cannot pre-buy this capacity
(for instance, it also has no outbound capacity or onchain funds).
* The client determines the parameters of a particular LSP via a `GET`
request.
* The client requests for a JIT channel, specifying how much it will
receive, via a `POST` request.
* The LSP returns an SCID, which identifies this request to the LSP.
* The client generates an invoice, which includes the above SCID and the
LSP node ID as a routehint.
* The client hands the invoice to whoever it will receive funds from.
* The payment is forwarded to the LSP.
* The LSP recognizes the next hop SCID as being a JIT channel request,
and opens a 0-confirmation channel to the client, which must be
connected to the LSP at that time.
* The LSP forwards the payment to the client, deducting the channel
opening fee.
* The client claims the payment.

### 1. API Information

`GET /lsp/jitchannel` is the entrypoint for each client using the API.
It indicates supported versions of this protocol, as well as any limits the
LSP imposes, and parameters for payment.

The client MUST pull `GET /lsp/jitchannel` to read:

- the supported `versions` of the LSP.
- the `opening_fee` of the LSP and its related parameters.

The client MUST then determine protocol compatibility, and also determine
if the fee imposed by the LSP is acceptable.

Example `GET /lsp/jitchannel` response:

```JSON
{
"versions": [1],
"opening_fee": "546000",
"opening_fee_valid_until": "2023-02-23T08:47:30.511Z",
"opening_fee_promise": "abcdefghijklmnopqrstuvwxyz",
"min_payment_size": "1000",
"max_payment_size": "1000000"
}
```

`versions` is the set of API versions the LSP supports.
When the client later contacts the LSP, it indicates a single specific
API version, which MUST be one of those indicated in this set.

`opening_fee` is how much the LSP will charge to open a JIT channel, in
millisatoshis.

`opening_fee_valid_until` is a datetime up to which the offered
`opening_fee` is valid.

`opening_fee_promise` is an arbitrary string that proves to the LSP
that it previously promised a specific `opening_fee` with a specific
`eopning_fee_valid_until`.

LSPs:

* SHOULD use a cryptographically-verifiable method of generating
`opening_fee_promise`, such as a MAC of some serialization of the
`opening_fee` and the `opening_fee_valid_until`, then encoded in
hexadecimal or other text encoding.
* MUST ensure the promise is no longer than 512 bytes.
* SHOULD avoid characters outside of the printable ASCII range.

Clients:

* MUST abort this flow if `opening_fee_promise` exceeds 512 bytes.
* MUST NOT parse or interpret this string, and only provide it
verbatim later.

> **Rationale** By using a promise that must be remembered by the
> client, the LSP does not have to remember what it offered via this
> API, reducing state storage, especially if the client then decides
> that the `opening_fee` is too high and ultimately decides not to
> continue this flow.
> By using a cryptographically-verifiable method, the LSP can ensure
> that it will only honour `opening_fee`s it actually promised.
> A size limit is imposed so that LSPs cannot burden clients with
> unreasonable storage requirements.
`min_payment_size` and `max_payment_size` are the limits of the
payment size, inclusive.
These are in millisatoshis.
The payment size is the amount that the client will receive on the
JIT Channel.

The client MUST ignore any additional fields it does not recognize.

> **Rationale** This allows future versions of this spec to add new
> fields to this response, without causing problems for clients that
> only support the current version.
### 2. Request JIT Channel

The client constructs a request body for a `POST /lsp/jitchannel`
request, depending on their need.

Example `POST /lsp/jitchannel` request:

```JSON
{
"version": 1,
"opening_fee": "546000",
"opening_fee_valid_until": "2023-02-23T08:47:30.511Z",
"opening_fee_promise": "abcdefghijklmnopqrstuvwxyz",
"payment_size": "42000",
"client_node_id": "03d4e028a0d4a90868ec202ab684fb0085779defea9ca7553e06146557631eec20"
}
```

`version` is the version of this spec that will be used for this
interaction.

`opening_fee`, `opening_fee_valid_until`, and `opening_fee_promise`
are the parameters acquired from the previous step.
Clients MUST copy them verbatim from some previous
`GET /lsp/jitchannel` response.
LSPs SHOULD check that the `opening_fee_promise` does in fact
prove that it previously promised the specified `opening_fee` and
`opening_fee_valid_until`.
LSPs SHOULD check that the `opening_fee_valid_until` is not a
past datetime.

`payment_size` is the amount that the client wants to receive.

The client MUST ensure that `payment_size` is within the previous
`min_payment_size` and `max_payment_size` parameters from the LSP.
The LSP MUST validate that the `payment_size` is within the previous
`min_payment_size` and `max_payment_size` parameters from the LSP.

The client MAY use a "subtractive" computation to get the
`payment_size`.
For example, the client may want to charge some payer an exact
amount of 1,000,000 millisatoshis, but the LSP indicated an
`opening_fee` of 546,000 millisatoshis.
In that case, the client should specify 454,000 millisatoshis for
`payment_size`, so that the invoice charges 1,000,000 millisatoshis
total.

`client_node_id` is the node ID of the client.

The LSP can then respond with a response object or an error
object.
The client can differentiate between these two objects by checking
for an `error` field, which exists and is the Boolean value
`true` if the object is an error object.

Example successful `POST /lsp/jitchannel` response:

```JSON
{
"jit_channel_scid": "1x4815x29451",
"lsp_node_id": "03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f",
"lsp_cltv_expiry_delta" : 144,
"lsp_connection_strings": [
"03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f@3.33.236.230:9735"
]
}
```

`jit_channel_scid` is the SCID to use for creating the routehint in
the invoice, `lsp_node_id` is the node for that routehint hop, and
`lsp_cltv_expiry_delta` is the CLTV delta for that routehint hop.

`lsp_connection_strings` is how the client should connect to the
LSP.

### 3. Invoice Generation

The client then generates a [BOLT11][] invoice.

[BOLT11]: https://github.com/lightning/bolts/blob/f7dcc32694b8cd4f3a1768b904f58cb177168f29/11-payment-encoding.md

* `amount` is the sum of `payment_size` and `opening_fee`.
Note that `payment_size` and `opening_fee` are in millisatoshis,
but the BOLT11 `amount` uses metric Bitcoin units.
* The sum of `timestamp` and `x`/`expiry` fields is equal to
or less than `opening_fee_valid_until`.
* `n` is the client node ID.
* `r` contains a single routehint with a single hop:
* `pubkey` is the `lsp_node_id`.
* `short_channel_id` is the `jit_channel_scid`.
* `fee_base_msat` and `fee_proportional_millionths` are 0.
* `cltv_expiry_delta` is `lsp_cltv_expiry_delta`.

All other fields are to be filled in by the client.

The client MAY indicate multipart (`basic_mpp`) support, if it
supports multipart.

### 4. Payment

The client MUST connect to the LSP via an indicated
`lsp_connection_strings`, and then issue the generated invoice
to the payer of the client.

The payer can then generate one or more outgoing payment parts to
deliver the total amount to the LSP.

The LSP, when it receives a forward where the next hop has an
SCID matching an issued `jit_channel_scid`:

* MUST wait for payment parts until all parts sum up to at least
`payment_size` plus `opening_fee`.
* MUST NOT fail with `mpp_timeout`, as the final hop is the client
and that error is only allowed at the final hop.
* MUST fail with `unknown_next_peer` if all parts have not
summed up to at least `payment_size` plus `opening_fee` AND
`opening_fee_valid_until` has passed.
* MAY fail with `unknown_next_peer` if it receives too many payment
parts.
* When all conditions below are true, MUST continue to the next
step:
* The current time is strictly less than `opening_fee_valid_until`.
* All received payment parts sum up to at least `payment_size`
plus `opening_fee`.
* The client is connected.

### 5. Channel Opening And Forwarding

The LSP requests a channel open to the client.
The LSP MUST set `option_zeroconf` in the channel opening.

The channel size must be sufficient, including up to 1% LSP-side
channel reserve, to forward the `payment_size` to the client.

The LSP then forwards parts to the client as soon as both client
and LSP have signalled `channel_ready` for the new channel.
The LSP rewrites onions to deduct, in total, `opening_fee` from
all parts it received, and to forward to the newly-opened channel.

The LSP MUST ensure that each forwarded part forwards at least
one millisatoshi.
The LSP MUST ensure that all parts forwarded sum up to at least
`payment_size`.

For example, the LSP can use the algorithm below to determine
how much to forward for each incoming payment part, while ensuring
that both the above properties are preserved.

* Put the payment parts in an array in arbitrary order.
* For each part:
* Get the `part_amount`, the incoming amount for the part.
* If `part_amount - 1 >= opening_fee`, then forward
`part_amount - opening_fee` for this part, then forward
the rest of the parts verbatim, if any.
* Else subtract `opening_fee = opening_fee - (part_amount - 1)`,
then forward 1 millisatoshi for this part.
* The above loop will not reach past the last part unless
the number of parts exceeds the minimum `payment_size`.

Once the client has received payment parts that sum up to at
least `payment_size`, it MUST claim at least one payment part.
Once that is done, the protocol flow is complete.

0 comments on commit 0fd471c

Please sign in to comment.