-
Notifications
You must be signed in to change notification settings - Fork 493
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
Trampoline Routing #654
Trampoline Routing #654
Conversation
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.
Even if it's already underscores, I think the difference between the packet-switching mechanism (trampoline _onion_packet) and the topology announcement one (requirement of knowing the full graph) is important. Thanks to the flexibility of the first one, we may have a different addressing which would enable a more decentralized topology. I really can see trampoline nodes being partial blinded themselves and just announce their connections to other trampolines ones and from then sender would compute a logical route of trampoline pairs.
wip-trampoline.md
Outdated
will even provide a bigger anonymity set). | ||
|
||
Nodes that keep track of the whole network should advertise support for `trampoline_routing`. This is an opportunity | ||
for them to earn more fees than with the default onion routing. |
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's about network partition of constrained nodes by channel squatting of concurrent trampoline node servicing same network area ? Intuition would say channel squatting would be more efficient than now as trampoline node as a better view of the network than constrained one
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.
Not sure what you mean there, could you expand?
Are you implying that trampoline nodes in the same area would have an incentive to attack each other's inbound capacity?
Do not forget that most likely all current routing nodes (nodes running on servers) will support trampoline. That means that a vast majority of the public network graph will support trampoline. Users of trampoline (mobile / constrained nodes) usually don't advertise their node or their channels.
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.
Yes as you said, was thinking about trampoline node attacking other trampoline node inbound capacity. It's a fuzzy concern if we have a lot of trampoline nodes and cost partition attack is high, but not if we have few some of them. Saying most likely all current routing nodes will support trampoline is IMO hard without empirical data from deployment, so maybe will should beware to not ask to high-requirement for being one (like also supporting wumbo channels)
* [`400*byte`:`hop_payloads`] | ||
* [`32*byte`:`hmac`] | ||
|
||
This results in a `466`-bytes fixed-size tlv where the value has exactly the same format as the `onion_packet` with |
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.
With a fixed 466
-bytes fixed-sizes is maximum size implicitly 120 hops (20 * 6) ? I think not given you have variable size payload, but even variable there is a minimum size to describe meaningfully HTLC routed..
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 would need to re-do the maths, but I think it's less than that.
With the trampoline onion inside a normal onion, the normal onion route can be at most ~15 hops.
And the number of trampoline hops will be at most 4 or 5 (would need to double-check).
So we would have maximum 60-hops route. And an attacker wouldn't control the route taken between trampoline hops so in reality the route will likely be less than that (this shouldn't increase too much the effectiveness of a capacity attack).
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 you right for the math didn't subtract the trampoline onion, maybe in future versions, sending node should be able to pick trampoline onion size as a parameter, and so increase number of trampolines (privacy would be a good reason)
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.
Yeah I'm trying to balance privacy (where long routes are better) with capacity attacks (where long routes are bad). This is an inherent trade-off with today's lightning and it's a real pain ;)
wip-trampoline.md
Outdated
Trampoline nodes should only accept and relay `node_update`s from nodes that have open channels with inbound and | ||
outbound capacity. | ||
|
||
If a node is not willing to relay trampoline payments, it will simply never send a `node_update`. This lets the network |
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 a node opt-out of being a trampoline one after some time ? (like while opening/closing/splicing channels)
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 think this will work fine. Trampoline nodes simply forward "normal" htlcs.
If you suddenly switch off the trampoline feature bit and refuse to route new trampoline payments, this wouldn't break anything on your side. It may be an issue for constrained nodes that still think you are a trampoline node, but they should route around you on failures and refresh their trampoline set at some point, evicting you from their DB.
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.
IMO would be nice to disable support cleanly to avoid useless failures and not having mission control/autopilot downgrading your score for bad reason. A bitfield node_flags
a la channel_update
would be cool, mostly if we have other routing features
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.
Interesting idea, that definitely could be done. Since you supported trampoline at some point that means your node contains the code for the node_update
message, so you could send a last node_update
setting a disable
bit. That would allow a clean downgrade. I'll include that.
wip-trampoline.md
Outdated
|
||
## Appendix C: Trampoline and MPP | ||
|
||
Trampoline routing combines nicely with multi-part payments. When multi-part payment is used, we can allow trampoline |
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.
Hmmm if a trampoline node has a good view of a network, knowing every last partial payment node, it should be able to do path intersections from them to discover who is the original sender. IMO, a randomly-generated one-shot tunnel with a minimal length would be better than splitting payment if we want to preserve payer-privacy towards first trampoline node. But this whole point need real analysis.
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.
Interesting point, thanks for raising this! This is an issue with normal AMP, isn't it? The recipient could de-anonymize the payer by doing path intersection (even though in reality, the payer's channels are likely unannounced channels so the recipient can't de-anonymize the first hop).
If I understand your attack correctly, it seems that on the contrary trampoline helps anonymity in that case. Because in that case a node is only able to de-anonymize the previous node, thus discovering who the previous trampoline hop was. But thanks to onion encryption, this doesn't tell the attacker whether that node was the payer or an intermediate trampoline node! Unless the payer doesn't advertise trampoline feature bits, in which case we are in the same spot as normal AMP privacy-wise.
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.
Let's say you have following topology:
______ B __________
/ \
/ \
A ___________ C _________ T
\ /
\ _______ D _________/
If all channels are publicly knew and that's the whole graph, and A is using T as trampoline node by sending a AMP payment through B, C and D, that's super easy to deduct than A is payer from T viewpoint. Now this topology is super dumb, and private channels would obfuscate real graph and make whole analysis probabilistic-based. So payer should use only private channels as first links to broadcast AMP payment. Like you said it should keep you safe but that's easy to mess up in practice ("Oh my two first channels are private, that should be enough, don't care than my third one is public !")
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.
But the example you're sharing showcases an issue with AMP without trampoline ;)
If this is a non-trampoline AMP where T is the recipient, T is able to deduce who the payer is.
In the trampoline case, T is only able to deduce that A was the previous trampoline node (which may be the payer of just another intermediate trampoline node). So it's just like knowing the previous hop in a normal payment route.
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 dumb, you're right I forgot a vertice from T the trampoline to some E node the payee.
Yes I think you're right that T is only able to deduce that A was the previous trampoline node (not necessarily the payer), but to keep analysis blurred we should recommend to use multiple trampoline/or private channels. If it's knew that a particular implementation uses only one-hop trampoline privacy would be broken.
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 completely agree. Implementations should never hard-code or bias too much towards a one-hop trampoline route. I'll stress this more in the rationale.
I completely agree. I'm not mentioning it yet because it is a larger change and I want to roll-out such things incrementally, but the next step after that first version of trampoline is very likely something like that. |
fc87581
to
0c002f3
Compare
This proposal allows nodes running on constrained devices to sync only a small portion of the network and leverage trampoline nodes to calculate the missing parts of the payment route.
0c002f3
to
fb4554d
Compare
Personally I think moving in this direction is a bad idea for two reasons:
|
@TheBlueMatt a sufficiently well-designed trampoline routing allows for payee secrecy from payer. Currently the payer has to know the payee or a node that directly has a channel to the payee. With a trampoline routing scheme that allows independent pre-concatenation, the payee can provide an encrypted trampoline route to itself in an invoice (i.e. rendezvous routing, i.e. very much like Tor hidden services) as well as payee-pays-fees (the payer is obligated to pay only up to the trampoline node, with any fees from the trampoline node to the payee being shouldered by the payee --- useful for c*stodial exchanges that are willing to publish their own node as a trampoline node, their Of course, that assumes we want the payee to have secrecy of which node on the network it actually is. And I am not at all certain the actual current proposal supports independent concatenation (i.e. having different sources encrypt different hops, which would be needed for rendezvous).
Given that large nodes tend to be the most online/successful, I think the two sets converge. Admittedly the latter set will probably start out larger than the former set, which improves risk-sharing, and probably dynamic growth will ensure the latter set will always be larger than the former set. |
@TheBlueMatt part of your privacy concerns is also mitigated if reduced-routemap nodes can also be trampolines. This requires that we allow independent pre-concatenation. Suppose there exists a node with a f*cking tiny routemap: it only knows its direct peers, and one large, high-uptime server that it uses for all paying anyone other than its direct peers (it does not even know a direct path to that server: it randomly selects a direct peer and puts a trampoline containing that peer -> server -> payee). The privacy of that node would be greatly improved if that node were to publicly publish itself as a rendezvous node. That would be viable if and only if trampolines supported pre-concatenation, i.e. if that node could take a pre-existing trampoline onion and prepend a few hops onto it. Suppose the large server receives a trampoline request. It could be:
This is basically a form of delegation. Admittedly, this is still not perfect when considering risk-sharing principle. This simply ensures more routes get to the large server: not only do non-myopic nodes have a chance to select the large server as a trampoline hop, but every myopic node that signals itself as a trampoline hop, and remembers this large server, will ensure that use of those myopic nodes as trampoline hops is nothing more than an alias for using the large server as a trampoline hop. So much for trampoline delegation. |
I'm aware of the benefits of trampoline routing for payee-secrecy, and would probably be in favor of trampoline routing with that as the explicit and only goal, but this proposal is not that, and you need go no further than the opening motivation in this PR to see that. Hence my vocal objection. A proposal for trampoline routing with an explicit goal of helping clients reduce their routemap size by relying on third parties to do their routing for them seems like about five steps backwards for lightning (and if you want to do this to your poor users, you can do it yourself without polluting the spec with it). |
Seems a good point. |
The reason I'm pushing this proposal is to foster discussion and brainstorm new ideas. Now onto the technical feedback, I disagree with your claims on the privacy impact. Privacy is only possible with a big enough network and some randomness in the route selection. Once we have a satisfactory solution to concatenate routes, it's highly likely that a majority of routing nodes will activate that feature (more opportunities to relay payments). That means you have a large set of potential nodes to sample, avoiding the issues you mention. I believe that, if done correctly, random sampling can provide more privacy and more opportunities for smaller nodes to relay payments. The current proposal should certainly be improved and that's why I'm asking for feedback.
Not really: the privacy benefits of trampoline can only be met if it is largely deployed on the network, hence the need for standardization. Of course a single-node deployment would be bad for privacy, but, again, the same is true for our current routing system. |
Trampoline routing also creates an incentive for relaying nodes to properly maintain a "good" view of the network. Such an incentive does not exist today since relaying nodes don't need a routing table to forward payments (you need routing info when you want to send payment, not when you're forwarding or receiving them). |
Why should such an incentive need to exist, for some reason of improved privacy or security or censorship-freedom or scaling? Why require the spending of resources if improvements are otherwise not achieved anyway? This should be considered a cost of trampoline, not a benefit, unless you can show that "if some other hypothetical feature XYZZY, not related to Trampoline, were existent, and had the property that it required relaying nodes to maintain a good view of the network, then we should enable that feature RIGHT NOW because it forces relaying nodes to maintain a good view of the network because ${REASON}". |
Well because the routing nodes are critical to enabling payment routing. Nothing to do with with privacy or security, but simply to make the system work in the first place. If the network is very private and very secure but the graph isn't connected, then Lightning is useless. People could make anonymous and secure payments, but in reality they can't because there's no routes to their destinations. You have a much better chance of having a healthy, well-connected graph when the nodes actually care about adding the right edges to improve connectivity, don't you think? That's a healthy incentive in my opinion to have routing nodes care about the graph instead of only wallets caring about it. But that's a side comment, we should probably focus on the main arguments about privacy/efficiency instead of forking the discussion too much. |
That is why we have fees. Fee-maximizing routing nodes will already strive to improve connectivity locally for themselves because by doing so, they can undercut competition and gain more fees, and multiple fee-maximizing routing nodes will then greatly improve the overall connectivity of the entire graph. Given that, an additional incentive is unnecessary and thus not an argument for this proposal regardless.
Yes. |
Aside from agreeing with @ZmnSCPxj here, I don't understand this concept. In today's lightning network, if every routing node in the network had literally zero view of other nodes in the network outside of their immediate neighbors, that would cause absolutely zero problems. They have no need to know about anything other than their neighbors except to open new channels. To reiterate, in general, I think the points about payee-privacy are really important, and if there were a proposal for trampoline routing which only supported payee-privacy in the form of invoice trampolines (with associated "hiding the fact that the end recipient is X from the intermediate node by having multiple hops be trampoines"), I probably would have less of an issue with it, but I find it somewhat astounding that we have to argue about whether its ok to export routing decisions to your next-hop, and given that somehow we are, would likely object to trampoline routing in general just to avoid people doing stupid things. |
If I understand your point correctly, I think we're in alignment there (so I really don't understand why you reject the whole proposal that strongly). It's true that I didn't remove yet the "pay to legacy recipient" section so it looks like you're loosing payee privacy every time you're using trampoline; however there are two open comments on this PR where I said that it will be removed in the next commits. That means a payee signals support for trampoline (in the invoice). And a payer uses multiple trampoline hops, so it seems to me that we're not losing any privacy compared to today's routing. I understand that this PR is big and takes time to review, so it's easy to dismiss it without reading the whole thing: that's because I wanted to give more context to help readers, fuel discussions, and make sure everyone sees the full picture. Maybe it was a mistake; it makes everyone focus only on the points they don't like and dismiss the rest. I'll push an update soon to at least remove the pay-to-legacy part: that will make the PR smaller and remove something we all agree is a bad idea for payee privacy. EDIT: 1bad26d makes trampoline an opt-in from the recipient. 32fd16e moves the concepts and high-level design to the proposal format cdecker is experimenting with; it will make this easier to review. |
Remove the ability to use a Trampoline node to pay a legacy node. It's a bad idea for recipient privacy and should be avoided.
The concept and more high-level ideas are moved to the proposals folder, while the spec details are kept in a wip bolt.
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.
Very nice proposal, I think this pretty much reflects what I remembered about the way we discussed trampoline before.
The only thing that seems worth optimizing in my view is the changes to the gossip protocol: the addition of a new node_update
message seems redundant with the addition of a new filtering. I'd personally prefer not adding even more statefulness to the connection (filters are attached to connections, which is very similar to bloom filtering which got us loads of issues). I'd rather make the new message more expressive: each trampoline node can select up to n
"adjacent" trampoline nodes, and provide "virtual channel" stats on how to get to those nodes, i.e., they'd sum up proportional fees, base fees and CLTV deltas with which they expect to reach each of the listed trampoline nodes. This is sufficient to have a rough estimate on what delta to use and how many fees to provision the trampoline hops with. The reason this works is because the virtual channel stats are a linear combination of the channels of prospective route the trampoline node expects to be using.
If desired we can also just add a TLV field to the existing node_announcement
which the resource constrained devices can query for. This could remove the need for a contiguous subnetwork that forwards node_update
s to exist, in order to transport the messages to the devices, i.e., it's backwards compatible.
| | +--------------------------------------------+ | | | | ||
| | | outgoing_cltv_value | | | | | ||
| | +--------------------------------------------+ | | | | ||
| | | payment_secret | | | | |
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 sure I understand why trampoline nodes should require access to the payment_secret
, shouldn't that be in the trampoline onion, destined for the recipient, or at most the last trampoline before the destination that doesn't support trampoline only? If the latter was the intended semantics it'd need a note to this regard.
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.
Or are they intended to be decoy secrets?
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 should make this clearer, there are two distinct payment_secret
s here to allow MPP to be aggregated at trampoline nodes before being re-split by the trampoline node when forwarding.
Let me know if these ASCII arts are better: https://github.com/ACINQ/eclair/blob/ce3629c98b07cdc914bd397fe45dd4bfd8338392/eclair-core/src/main/scala/fr/acinq/eclair/wire/Onion.scala#L59
The idea is that we need to support MPP payments split between multiple different trampoline routes (those need a payment_secret
in the inner, trampoline onion) and using MPP between trampoline nodes to forward trampoline payments efficiently (those needs a different, unrelated payment_secret
in the outer, normal onion).
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 ok, that makes sense, but wouldn't that also be possible just by aggregating across the payment_hash
? Barring accidental reuse of the hash for different destinations (which is inherently unsafe anyway) it should work just as well.
FWIW even the concurrent reuse case is just a special case of the general reuse case, so I don't think it needs special treatment.
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 would work but you'd lose the probing protection that the payment_secret
brings, so a node Mallory that's just before a trampoline node Ted could guess that Ted is either the payment final recipient or a trampoline node. Not sure they could steal fees, but they might want to try which is bad for the payment success rate, so it felt better to keep the payment_secret
mechanism.
I agree, we could get rid of the |
Closing this PR in favor of:
|
This proposal allows nodes running on constrained devices to sync only a small portion of the network
and leverage trampoline nodes to calculate the missing parts of the payment route.
The main idea is to use layered onions: a normal onion contains a smaller onion for the last hop of the route, and that smaller onion contains routing information to reach the next trampoline hop.
This PR is split in two files. Reviewers should start with
proposals/trampoline.md
, where concepts and designs are presented at a higher level. This document lets reviewers see the big picture and how all the pieces work together.Then reviewers can move on to
wip-trampoline.md
which contains an aggregate of the spec sections that will be incorporated into existing bolts. This is following the usual spec format, this is where we'll work on the nitty-gritty details once we agree on the concept.We don't need to implement all features from the start. Trampoline could be a succession of independent features, each bringing an incremental addition to the protocol:
node_update
messages in a third PR