diff --git a/blip-0019.md b/blip-0019.md new file mode 100644 index 0000000..0f81cbc --- /dev/null +++ b/blip-0019.md @@ -0,0 +1,136 @@ +``` +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 increase 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, + * 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. This includes + received payments as well as forwarded ones. + * 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 + +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 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 +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. + +`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. +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? + +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