-
Notifications
You must be signed in to change notification settings - Fork 46
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
Add a bLIP for backwards-compatible inbound fees #22
base: master
Are you sure you want to change the base?
Conversation
Disclaimer: I might cross post this to the mailinglist. Let's say Alice charges During fee computation in forwarding Alice would only reduce the Here my questions:
What I am trying to say. Just having one node initially suggest a price for routing and heaving the channel partner make a counter suggestion by either adding to or subtracting from the amount and then keeping or paying the difference seems extremely unstable. While I very much like from this proposal that this conflict may not be directly visible to the remainder of the network I think we need some form of protocol for Alice and Bob to decide how to split the routing fees on the channel (similar to how we do onchain fee negotaion in mutual closes) and define a point after which Alice or Bob would fail the channel because they can't find agreement. Luckily various dialects of this problem have been studied in game theory. E.G:
There for some similar dialect of the problem it seems that the nash equlibrium is to split the revenue in a 50/50 way. Thus if we don't know any better it seems very reasonable to have a round based communication protocol (similar to channel closing) by which Alice and Bob negotiate the total routing fees which then would be split 50/50 betweetn them. btw: As mentioned of Twitter I have previously informed the Lightning Labs team about the fact that the question how to split the routing revenue between the partners needs to be addressed in any form of inbound fees as we would otherwise create instability in the network. Also let me be clear. To the best of my knowledge price signals (as routing fees are) are known to be a poor mechanism for flow control in fluid networks (like the electric grid or gas / water networks) as they usually do not provide stability. Valves that I have previously suggested to use tend to work much better for flow and congestion control. However also the valves approach would benefit form a communication protocol for the peers to agree on how much to open the valve in which direction. Similar to the negotiation of the routing fee one could have a more general communication protocol to negotiate channel meta data like fees / valves and other features. Conclusion: Maybe the current discussion and disagreement could be resolved by thinking about channel meta data negotiation protocols (which btw could also include some form of information sharing as proposed in lightning/bolts#780 ) and could be used even during channel opening negotiation. |
The HTLC will fail.
You're assuming they have a target total fee for the channel. I don't think that's a given - rather, a node may wish to receive X for flows inbound over a channel, irrespective of their peer's fee. We could also take your questions further - you could make a similar argument between a peer and the average (or min/max or whatever) fees its peer charges for outbound forwards. Nodes are in effect "splitting the revenue" of an HTLC through the full path, not just on one single hop. |
More generally, however, see the motivation section of the bLIP here - even if we assume routing nodes don't want this, nodes may want it on private channels for LSP clients. |
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.
While I'm still not sure whether inbound fees make sense or not (and how much instability they'd create), I like this proposal better than #18 and it's really trivial to implement, which is a good argument at least for a prototyping phase.
I share the concern of others wondering if inbound fees actually solve a problem, and don't just cater to the wishes to have more flexibility for the sake of it, but this proposal is definitely better and less infectious than #18. I'm still pretty convinced that the scenarios used to show the necessity if inbound fees can be solved by emulating them with existing parameters too, or perceived issues in the scenarios are not real (net income is likely unaffected by a node leeching all the outbound balance through a direct peering). |
blip-0019.md
Outdated
|
||
## 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. |
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.
This means that a routing node can only charge an inbound fee if its peer cooperates and may cause existing peering relationships to change. Especially if a node wants to charge inbound fees across the board in order to reduce outbound fees, all of its peers need to support this.
With #18, you can charge inbound fees as you like independent of your peers. Of course the limitation there is that senders need to support 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.
I'm not really sure I get this - a user may want to charge an inbound fee today, but they don't. Sure, once you have an implementation you may also ask your peer to support it, but it doesn't mean your relationship changes with your peer, unless of course they also support this feature. You may choose to prefer peers which do support this feature, sure, but isn't that true for any feature? Even for #18 you may prefer to use peers that use negative fees to give a discount in line with the second suggested motivation here.
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'm just saying that there is a difference between requiring your peer to support a feature vs requiring the sender of a payment to support a feature.
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.
Sure, one is local and one is global :)
* 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. |
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.
How can the node know what the rate limits are? They may be applied anywhere on the network. Or just a grace period?
Then if there are still senders who haven't received the update after the grace period, the node will start returning fee_insufficient
and still see its reputation damaged because of its peer inbound fee update? Not sure if the incentives are properly aligned here.
Does the delaying add complexity in the implementation because you need to keep track of history - potentially across restarts?
The situation that I described in the comment would be useful to add here too so that implementers understand why this is important. In the BOLTS I find that there isn't always enough rationale recorded, and it gets forgotten.
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.
How can the node know what the rate limits are? They may be applied anywhere on the network. Or just a grace period?
That is up to individual nodes. Its deliberately phrased in terms of channel_update
to indicate to nodes that they should use their existing rate-limiting logic they already have in place.
Then if there are still senders who haven't received the update after the grace period, the node will start returning fee_insufficient and still see its reputation damaged because of its peer inbound fee update? Not sure if the incentives are properly aligned here.
Hmm? No, this is not the case, the downstream node now is the one that gets to send the failure message (as its the one that is spamming updates) the upstream node forwarded the HTLC with stale parameters so that it wasnt blamed.
Does the delaying add complexity in the implementation because you need to keep track of history - potentially across restarts?
No more than existing delays in channel_update, basically. I mostly reused the tracking logic from there.
The situation that I described in the comment would be useful to add here too so that implementers understand why this is important. In the BOLTS I find that there isn't always enough rationale recorded, and it gets forgotten.
Good point, added more details.
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.
That is up to individual nodes. Its deliberately phrased in terms of channel_update to indicate to nodes that they should use their existing rate-limiting logic they already have in place.
What I mean is that a node's existing rate-limiting logic may not match what other nodes on the network do. The node broadcasts its channel_update
, but then it is held back somewhere on the network between this node and a potential sender of a payment. How do you implement this concretely?
Hmm? No, this is not the case, the downstream node now is the one that gets to send the failure message (as its the one that is spamming updates) the upstream node forwarded the HTLC with stale parameters so that it wasnt blamed.
Let's take the example A->B->C->D again. D set an inbound fee, C broadcasted a new channel_update
.
Then at some point, C receives an htlc to forward with an insufficient fee. There are two reasons why this could be:
- Channel update hasn't reached the sender yet
- Node B is not forwarding enough.
Now what is C going to do? Return fee_insufficient and potentially damage its reputation because D wanted to change its inbound fee? Or forward an insufficient amount to D and punish D while B is at fault really.
If no node ever wants to return fee_insufficient
, they can just keep forwarding an amount that is too small until the final destination is reached. Seems that things get a bit strange then?
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.
What I mean is that a node's existing rate-limiting logic may not match what other nodes on the network do. The node broadcasts its channel_update, but then it is held back somewhere on the network between this node and a potential sender of a payment. How do you implement this concretely?
This is no different from any other fee on the network today. Yes, there's active discussion in setting a more common rate-limit across the network, but in general senders have to be tolerant of this and recipients should expect it sometimes.
Now what is C going to do? Return fee_insufficient and potentially damage its reputation because D wanted to change its inbound fee? Or forward an insufficient amount to D and punish D while B is at fault really.
C can tell the difference, though! If B didn't forward enough to C, C will note that it didn't get enough fee compared to the forwarding instructions in the onion, and will then fail back with fee_insufficient
.
blip-0019.md
Outdated
|
||
## 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. |
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'm just saying that there is a difference between requiring your peer to support a feature vs requiring the sender of a payment to support a feature.
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`. |
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.
The observed delay is also influenced by the peer that is charging the inbound fee for this node (grace period). If those periods don't line up, this node is going to return fee_insufficient
and damage its reputation?
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.
Ah, luckily there's a super trivial solution - wait until you also see the channel_update. I mentioned that now.
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 don't think it is that trivial at all. You can wait until you see the channel_update, but that doesn't tell you for how long your peer will underpay you to account for propagation of that update to the sender.
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.
No, it is trivial - the forwarder should wait to enforce it until it has a chance to broadcast a new channel_update
, at which point it MUST enforce the update. The recipient/inbound-fee-setter should delay enforcement until it sees the channel_update
+ 10 minutes (which is congruous with what it does for channel_update
s normally). That shouldn't have any disagreement. If you prefer we could also apply the 10 minute timer on the forwarder's side, but its not a huge deal to send back the updated channel_update
when failing.
Another fee model that has been talked about in the past is 'pair-wise' fees. In that model, a routing node can assign a specific fee for each combination of in and out channel. With the gossip approach this is mostly an extension of #18 with a more advanced data format. Is there any way to do pair-wise fees with the proposal in this PR? |
The proposal specifies that inbound fees must be paid to the final hop too. If two routing nodes decide to open a direct channel to route traffic with inbound fees (charged to a distant sender), they can no longer use this channel to make 'free' payments between them. For example two custodial wallet nodes that route traffic but also make direct payments to each other. This looks to me like something to not step over too easily. |
Please for the love of god do not make
No, for the same reason as above :)
This is not a change from today. If a node decides it wants to charge its peer for sending it payments it can do so by creating fake hops in invoices. |
That's the naive way to do it. But there surely are different options. For example: every channel can be assigned a group (id) that is communicated as part of the channel update. For pair-wise fees, you can then reference a whole group of channels and set a different fee only for that group. Not saying that this is how it should be, but I do value the extensibility that the gossip model offers if a need for this would arise in the future.
I am not saying that they can't do so today. It's the opposite. If the mechanism proposed in this PR would be implemented, then routing nodes that charge inbound fees for traffic that they forward wouldn't be able to do zero-fee payments with direct peers anymore across those channels. |
< Not saying that this is how it should be, but I do value the extensibility that the gossip model offers if a need for this would arise in the future. If we end up deciding we need that feature, we can implement it any way we want to at that point :) I don't want to implement a router that lets nodes turn themselves into a bunch of virtual nodes in the graph, though :p.
Sure they can! They can negotiate any additional optional protocol they want :). "If invoice is to me, feel free to pay a fake invoice with funds less by the inbound fee amount", problem solved :). By making this a thing that is negotiated between two peers the two peers can negotiate any additional anything they want. |
Listening to the discussion during the call one thing came to mind: we are handing one peer a way to trigger a Then again, they are always free to reject anything that doesn't match their own policy, but that can cause more failed payments (the malicious node is also hurting themself, so 🤷 ) Didn't want to bring this up since the discussion was on a more fundamental level :-) |
Yes, the node asking for a fee update has to wait for their peer to send back (and thus broadcast) an updated |
This provides an alternative to #18. In comparison, it:
channel_update
messages due to negative fees being a function of channel balance by clamping the fee to zero at the protocol level.