-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0b195ee
commit 0fd471c
Showing
1 changed file
with
317 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |