From aa0b229863adc866f9bfdbcd5b59ff2220e4cee7 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 9 Jan 2023 18:44:17 +0000 Subject: [PATCH 1/4] Add a bLIP for backwards-compatible inbound fees --- blip-0019.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 blip-0019.md diff --git a/blip-0019.md b/blip-0019.md new file mode 100644 index 0000000..c99755b --- /dev/null +++ b/blip-0019.md @@ -0,0 +1,86 @@ +``` +bLIP: 19 +Title: Inbound Routing Fees +Status: Active +Author: Matt Corallo +Created: 2023-01-08 +License: CC0 +``` + +## Abstract + +This bLIP describes a mechanism whereby a node can charge either a positive or a negative amount in fees for an HTLC based on the channel on which the HTLC came in to said node. It does not modify existing `channel_update` messages, avoiding issues where temporary negative fees cause nodes to spam the gossip network (see "Rate Cards" for a proposal which adds negative fees without this issue). Instead, it relies on informing peers that a fee will be charged, and having them incrase their corresponding outbound fees. + +## Copyright + +This bLIP is licensed under the CC0 license. + +## Specification + +One new message is defined, `inbound_fees_update`: + +1. type: 34242 (`inbound_fees_update`) +2. data: + * [`32*byte`:`channel_id`] + * [`i32`:`inbound_forwarding_fee_proportional_millionths`] + * [`i32`:`inbound_forwarding_fee_base_msat`] + +Additionally, one new feature flag is defined: + +| Bits | Name | Description | Context | Dependencies | +|---------|----------------|--------------------------------------------------------|---------|--------------| +| 282/283 | `inbound_fees` | Supports receiving and enforcing `inbound_fees_update` | IN | None | + +### Requirements + +A node receiving `inbound_fees_update`: + * MUST ensure it's next `channel_update` message for the corresponding channel + has its `fee_proportional_millionths` and `fee_base_msat` fields incremented + by the `inbound_forwarding_fee_proportional_millionths` and + `inbound_forwarding_fee_base_msat` fields, respectively. Fields which fall + below zero MUST be set to zero. + * SHOULD ensure that it's next `channel_update` goes out in a timely manner, + subject to relevant rate-limits. + * MUST increase the amount forwarded in an HTLC by the advertised inbound fees. + +A node sending `inbound_fees_update`: + * SHOULD NOT send such a message more often than it anticipates + `channel_update` messages may be accepted by the gossip network. + * MUST verify that inbound fees corresponding with the provided settings are + paid on all HTLCs, noting that the inbound fees are calculated against the + inbound HTLC amount *before* the inbound fees are subtracted. + +## Rationale + +Because a node cannot set the fee fields in its `channel_update` below zero, +only a node's immediate peer may utilize negative inbound fees in excess of +its outbound fees. This is useful for private channels. + +Because senders calculate fees based on the amount as they think it will be +forwarded, inbound fees must be checked by adding required fees back up from +the `amt_to_forward` value. i.e. in order to check the total fee on an HTLC, a +node must calculate the total expected fee based on it's announced forwarding +parameters, subtract that from the `amt_to_forward` to get the amount the +sending node (likely) expected the processing node to receive. From there, the +processing node can calculate the inbound fee it expected and check that it was +included in the forwarded HTLC. + +## Motivation + +Many lightning node operators have expressed a desire for "inbound routing fees," i.e. fees which a sender must pay when forwarding *inbound* through a channel, rather than outbound. There is some debate as to whether such fees make sense in the general case - ultimately it's not the fee-charging node's liquidity which is being used here, so why can they charge a fee for it? + +However, ignoring whether this feature makes sense for routing nodes, routing nodes may which to use this to provide fee discounts for peers with which they have a commercial relationship with. For example LSP's may wish to use this to provide explicit fee discounts to their paying clients. + +Having a standard, interoperable way for such relationships to be implemented allows LSP's to provide such a service without vendor lockin. + +## Universality + +This bLIP describes a mechanism for inbound fees which is completely transparent to the broader lightning network. Only the two nodes involved in the channel are aware of the inbound fees. More importantly, due to the above concerns expressed over the general applicability of inbound routing fees, it is anticipated that not all lightning implementations will support this. Users wishing to charge inbound fees may seek out peers which support it, and LSP clients may wish to use this when working with an LSP to receive a fee discount. + +## Backwards Compatibility + +The new messages described in the bLIP are gated by a new feature bit, which nodes MAY set to odd to ensure backwards compatibility. + +## Reference Implementations + +* LDK: https://github.com/lightningdevkit/rust-lightning/pull/1942 From dab43c23dd35d8e17e76e2b2b2d5a4362c5b2d26 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 11 Jan 2023 19:18:37 +0000 Subject: [PATCH 2/4] Clarifications from Joost --- blip-0019.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/blip-0019.md b/blip-0019.md index c99755b..572d45e 100644 --- a/blip-0019.md +++ b/blip-0019.md @@ -41,20 +41,28 @@ A node receiving `inbound_fees_update`: below zero MUST be set to zero. * SHOULD ensure that it's next `channel_update` goes out in a timely manner, subject to relevant rate-limits. - * MUST increase the amount forwarded in an HTLC by the advertised inbound fees. + * MUST increase the amount forwarded in an HTLC by the advertised inbound fees, + * however SHOULD delay increasing the amount forwarded by an updated inbound + fee until it has a chance to broadcast a new `channel_update` after + rate-limits. A node sending `inbound_fees_update`: * SHOULD NOT send such a message more often than it anticipates `channel_update` messages may be accepted by the gossip network. * MUST verify that inbound fees corresponding with the provided settings are paid on all HTLCs, noting that the inbound fees are calculated against the - inbound HTLC amount *before* the inbound fees are subtracted. + inbound HTLC amount *before* the inbound fees are subtracted. This includes + received payments as well as forwarded ones. + * SHOULD delay enforcing updated inbound fees for some time, congruous with + the delay applied when enforcing new fees after sending a `channel_update`. ## Rationale Because a node cannot set the fee fields in its `channel_update` below zero, only a node's immediate peer may utilize negative inbound fees in excess of -its outbound fees. This is useful for private channels. +its outbound fees. This may be useful for private channels where a peer can +provide a fee discount to its counterparty even though it is not available to +the global network. Because senders calculate fees based on the amount as they think it will be forwarded, inbound fees must be checked by adding required fees back up from @@ -65,6 +73,13 @@ sending node (likely) expected the processing node to receive. From there, the processing node can calculate the inbound fee it expected and check that it was included in the forwarded HTLC. +Note that inbound fees are charged both on forwarded payments and inbound +payments to prevent a forwarding node from probing to determine if the next hop +is the final destination by checking if the recipient enforces inbound fees. +This also ensures that nodes charging inbound fees for the purpose of +encouraging HTLCs be routed over a given path applies to all HTLCs, not only a +subset. + ## Motivation Many lightning node operators have expressed a desire for "inbound routing fees," i.e. fees which a sender must pay when forwarding *inbound* through a channel, rather than outbound. There is some debate as to whether such fees make sense in the general case - ultimately it's not the fee-charging node's liquidity which is being used here, so why can they charge a fee for it? From 970096769b9a627a6c004c426a97a41ef2ba2257 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 11 Jan 2023 19:18:50 +0000 Subject: [PATCH 3/4] Fix wrapping --- blip-0019.md | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/blip-0019.md b/blip-0019.md index 572d45e..782aa37 100644 --- a/blip-0019.md +++ b/blip-0019.md @@ -9,7 +9,13 @@ License: CC0 ## Abstract -This bLIP describes a mechanism whereby a node can charge either a positive or a negative amount in fees for an HTLC based on the channel on which the HTLC came in to said node. It does not modify existing `channel_update` messages, avoiding issues where temporary negative fees cause nodes to spam the gossip network (see "Rate Cards" for a proposal which adds negative fees without this issue). Instead, it relies on informing peers that a fee will be charged, and having them incrase their corresponding outbound fees. +This bLIP describes a mechanism whereby a node can charge either a positive or a +negative amount in fees for an HTLC based on the channel on which the HTLC came +in to said node. It does not modify existing `channel_update` messages, avoiding +issues where temporary negative fees cause nodes to spam the gossip network (see +"Rate Cards" for a proposal which adds negative fees without this issue). +Instead, it relies on informing peers that a fee will be charged, and having +them increase their corresponding outbound fees. ## Copyright @@ -82,19 +88,34 @@ subset. ## Motivation -Many lightning node operators have expressed a desire for "inbound routing fees," i.e. fees which a sender must pay when forwarding *inbound* through a channel, rather than outbound. There is some debate as to whether such fees make sense in the general case - ultimately it's not the fee-charging node's liquidity which is being used here, so why can they charge a fee for it? +Many lightning node operators have expressed a desire for "inbound routing +fees," i.e. fees which a sender must pay when forwarding *inbound* through a +channel, rather than outbound. There is some debate as to whether such fees make +sense in the general case - ultimately it's not the fee-charging node's +liquidity which is being used here, so why can they charge a fee for it? -However, ignoring whether this feature makes sense for routing nodes, routing nodes may which to use this to provide fee discounts for peers with which they have a commercial relationship with. For example LSP's may wish to use this to provide explicit fee discounts to their paying clients. +However, ignoring whether this feature makes sense for routing nodes, routing +nodes may which to use this to provide fee discounts for peers with which they +have a commercial relationship with. For example LSP's may wish to use this to +provide explicit fee discounts to their paying clients. -Having a standard, interoperable way for such relationships to be implemented allows LSP's to provide such a service without vendor lockin. +Having a standard, interoperable way for such relationships to be implemented +allows LSP's to provide such a service without vendor lockin. ## Universality -This bLIP describes a mechanism for inbound fees which is completely transparent to the broader lightning network. Only the two nodes involved in the channel are aware of the inbound fees. More importantly, due to the above concerns expressed over the general applicability of inbound routing fees, it is anticipated that not all lightning implementations will support this. Users wishing to charge inbound fees may seek out peers which support it, and LSP clients may wish to use this when working with an LSP to receive a fee discount. +This bLIP describes a mechanism for inbound fees which is completely transparent +to the broader lightning network. Only the two nodes involved in the channel are +aware of the inbound fees. More importantly, due to the above concerns expressed +over the general applicability of inbound routing fees, it is anticipated that +not all lightning implementations will support this. Users wishing to charge +inbound fees may seek out peers which support it, and LSP clients may wish to +use this when working with an LSP to receive a fee discount. ## Backwards Compatibility -The new messages described in the bLIP are gated by a new feature bit, which nodes MAY set to odd to ensure backwards compatibility. +The new messages described in the bLIP are gated by a new feature bit, which +nodes MAY set to odd to ensure backwards compatibility. ## Reference Implementations From 5556f5effdefd44b1959efc2a5496942c94fc40b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 13 Jan 2023 20:58:55 +0000 Subject: [PATCH 4/4] add more rationale and additional sender delay --- blip-0019.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/blip-0019.md b/blip-0019.md index 782aa37..0f81cbc 100644 --- a/blip-0019.md +++ b/blip-0019.md @@ -59,7 +59,8 @@ A node sending `inbound_fees_update`: paid on all HTLCs, noting that the inbound fees are calculated against the inbound HTLC amount *before* the inbound fees are subtracted. This includes received payments as well as forwarded ones. - * SHOULD delay enforcing updated inbound fees for some time, congruous with + * SHOULD delay enforcing updated inbound fees until it sees an updated + `channel_udpate` from its peer and for some time thereafter, congruous with the delay applied when enforcing new fees after sending a `channel_update`. ## Rationale @@ -79,6 +80,19 @@ sending node (likely) expected the processing node to receive. From there, the processing node can calculate the inbound fee it expected and check that it was included in the forwarded HTLC. +`channel_update` messages are generally rate-limited across the gossip network +and, thus, are generally rate-limited on the sender side as well. Therefor, +nodes already accept stale forwarding parameters for some time after a +`channel_update` goes out. A similar procedure has to exist here - nodes must +wait for a `channel_update` to propagate before they can enforce the new fee. +However, if the node that receives an `inbound_fees_update` message immediately +fails an HTLC due to incorrect parameters without ensuring its `channel_update` +has propagated, it may be scored negatively by senders which are overly +aggressive about node-level scoring. Thus, the recipient of the +`inbound_fees_update` is allowed to forward HTLCs with stale parameters until +it can get the `channel_update` out, ensuring the correct node is scored by +senders. + Note that inbound fees are charged both on forwarded payments and inbound payments to prevent a forwarding node from probing to determine if the next hop is the final destination by checking if the recipient enforces inbound fees.