-
Notifications
You must be signed in to change notification settings - Fork 54
bLIP-0052: Add ongoing proportional fees #63
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -224,6 +224,7 @@ Example `lsps2.get_info` result: | |
| { | ||
| "min_fee_msat": "546000", | ||
| "proportional": 1200, | ||
| "ongoing_proportional": 1000, | ||
| "valid_until": "2023-02-23T08:47:30.511Z", | ||
| "min_lifetime": 1008, | ||
| "max_client_to_self_delay": 2016, | ||
|
|
@@ -234,6 +235,7 @@ Example `lsps2.get_info` result: | |
| { | ||
| "min_fee_msat": "1092000", | ||
| "proportional": 2400, | ||
| "ongoing_proportional": 500, | ||
| "valid_until": "2023-02-27T21:23:57.984Z", | ||
| "min_lifetime": 1008, | ||
| "max_client_to_self_delay": 2016, | ||
|
|
@@ -250,8 +252,8 @@ The LSP MAY return an empty array; in which case, the client currently | |
| cannot use JIT Channels with this LSP. | ||
|
|
||
| An `opening_fee_params` object describes how much the LSP will charge for a | ||
| channel open, what payment sizes it will accept, and until when the described | ||
| parameters will be considered valid. | ||
| channel open, what payment sizes it will accept, ongoing fees for subsequent | ||
| payments, and until when the described parameters will be considered valid. | ||
| An `opening_fee_params` object MUST have all of the following fields, | ||
| and MUST NOT have any additional fields: | ||
|
|
||
|
|
@@ -267,6 +269,12 @@ and MUST NOT have any additional fields: | |
| `min_fee_msat` is paid instead of the proportional times payment size | ||
| divided by 1 million. | ||
| [<LSPS0.ppm>][] | ||
| * `ongoing_proportional` is a parts-per-million number that describes how many | ||
| millisatoshis to charge for every 1 million millisatoshis of payment | ||
| size for each payment after the first payment that opened the channel. | ||
| This fee is charged on every forwarded payment through the channel after | ||
| the initial channel-opening payment. | ||
| [<LSPS0.ppm>][] | ||
| * `valid_until` is a datetime (as an ISO8601 string) up to which this specific | ||
| `opening_fee_params` is valid, and also serves as the timeout for the JIT | ||
| Channel flow, if this particular object is selected. | ||
|
|
@@ -294,8 +302,8 @@ and MUST NOT have any additional fields: | |
| to the client, not including the forwarding fees of nodes along the way. | ||
| * `promise` is an arbitrary LSP-generated string that proves to the LSP that | ||
| it has promised a specific `opening_fee_params` with the specific | ||
| `min_fee_msat`, `proportional`, `valid_until`, `min_lifetime`, | ||
| `max_client_to_self_delay`, `min_payment_size_msat`, and | ||
| `min_fee_msat`, `proportional`, `ongoing_proportional`, `valid_until`, | ||
| `min_lifetime`, `max_client_to_self_delay`, `min_payment_size_msat`, and | ||
| `max_payment_size_msat`. | ||
|
|
||
| > **Rationale** A "minimum" fee is used instead of an additive base fee as | ||
|
|
@@ -553,6 +561,7 @@ Example `lsps2.buy` request parameters: | |
| "opening_fee_params": { | ||
| "min_fee_msat": "546000", | ||
| "proportional": 1200, | ||
| "ongoing_proportional": 1000, | ||
| "valid_until": "2023-02-23T08:47:30.511Z", | ||
| "min_lifetime": 1008, | ||
| "max_client_to_self_delay": 2016, | ||
|
|
@@ -1029,6 +1038,33 @@ selected. | |
| LSPs MUST consider this alias not just for forwarded payments, but | ||
| also for onion messages. | ||
|
|
||
| #### Ongoing Proportional Fees | ||
|
|
||
| For all payments forwarded through the channel after the initial | ||
| channel-opening payment, the LSP MUST charge an ongoing proportional | ||
| fee as specified in the `ongoing_proportional` field from the | ||
| `opening_fee_params` used to open the channel. | ||
|
|
||
| The ongoing fee for each payment is computed as: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should repeat the computation here, but rather just refer to the other parts of the spec. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only potential confusion is that in the 'computing the fee' section that is for the opening fee which includes the min_fee portion. The ongoing_fee as defined only includes the proportional component of the fee. |
||
|
|
||
| ongoing_fee = ((payment_amount_msat * ongoing_proportional) + 999999) / 1000000 | ||
|
|
||
| Where `payment_amount_msat` is the amount being forwarded to the client, | ||
| and `ongoing_proportional` is the value from the `opening_fee_params`. | ||
|
|
||
| * All numbers MUST be computed using the same overflow detection rules | ||
| specified in the "Computing The `opening_fee`" section. | ||
| * The LSP MUST deduct this `ongoing_fee` from each forwarded payment. | ||
| * The LSP MUST include an `extra_fee` TLV (type 65537) in the | ||
| `update_add_htlc` message for each payment that has ongoing fees | ||
| deducted, with the value set to the computed `ongoing_fee`. | ||
| * The client MUST accept these fee deductions and validate that the | ||
| `extra_fee` matches the expected `ongoing_fee` calculation. | ||
|
|
||
| This ongoing fee allows LSPs to distribute the cost of channel opening | ||
| across the lifetime of the channel rather than charging the full amount | ||
| upfront on the first payment. | ||
|
|
||
| [<LSPS0.msat>]: ./blip-0050.md#link-lsps0msat | ||
| [<LSPS0.ppm>]: ./blip-0050.md#link-lsps0ppm | ||
| [<LSPS0.datetime>]: ./blip-0050.md#link-lsps0datetime | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't just add a field here as it would render all historical promises invalid. If we want to make such a change, it needs to be backwards compatible (read: additive), e.g., you could add a flag to the
get_inforesult that would indicate that the agreed upon fees will be withheld on every forward, and then the service would need to reject any buy requests that have that field unset (i.e., if they don't know it).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Pushed new commit that moved it to a flag outside of the params instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, as I went to implement this in ldk and ldk-node I realized that it's tough to avoid rendering historical promises invalid. Even if we move
ongoing_proportionaloutside theopening_fee_paramsthen we still would ideally want to include it in the generation of thepromise.If we do not include it in the promise then the LSP has no way to know what value it gave out as a response to a
get_inforequest and cannot validate the value provided in thebuyrequest.The alternatives would be:
Store a mapping from
promisetoongoing_proportionalfor each promise given out. This seems like not a great idea as the whole point of the promise is for the LSP to remain stateless when handling get_info requests.Use a static
ongoing_proportionalvalue across all requests. This is less flexible but maybe acceptable (if it's the only option)? Seems like it might run into issues should the LSP ever want to change it as someone who received a get_info request with the old value will run into unexpected behavior should they issue a buy request after the new value is set by the LSP. Even if you require the client to send the value they received to the user, the LSP cannot trust it because it's not included in the promise.Any thoughts?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had made a PR before that allows making backward compatible changes to the calculation of the
promisefor theopening_fee_params. It was discussed then that if we want to add fields to theopening_fee_params, that would be a good time to revisit. This is the PR in question: BitcoinAndLightningLayerSpecs/lsp#111Let me know if that helps your case.