-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
WIP: Route Blinding [1/n]: TLV Record Definition and Blind Hop Processing #7195
base: master
Are you sure you want to change the base?
WIP: Route Blinding [1/n]: TLV Record Definition and Blind Hop Processing #7195
Conversation
equip the onion payload with additional fields for route blinding, namely the recipient_encrypted_data and blinding_point fields.
These records comprise the route blinding payload which processing nodes will need in order to forward payments in the blinded portion of a route.
See ‘Requiring external module code from your own repository fork’ from https://go.dev/doc/modules/managing-dependencies NOTE: this commmit can be removed once the 'lightning-onion' dependency is merged and in use by lnd.
Add ability to parse route blinding payload after it is decrypted, and validate presence and omission of TLV payloads according to BOLT-04. This does not perform all BOLT-04 TLV payload validation. We now have validation to do across two levels of TLV payloads (top level onion TLV payload & route blinding TLV payload) and the contents of the UpdateAddHTLC message. What is present in one payload effects our expectation of what is present in the other payload. As a result, we will need to validate the payloads together, which means waiting til after the route blinding payload is decrypted. We preserve the normal validation in the case we are forwarding for a normal (not blinded) route. When an onion contains an encrypted route blinding payload, we validate what we are able to as soon as the route blinding payload is parsed. Although enforcing different portions of the onion and route blinding payload validation in different stages of processing for a blind hop is a bit more complex, it provides a benefit over deferring validation in that we are able to fail early on in the processing and avoid unecessary computation only to fail later.
The ChannelLink’s decision about whether it is processing a final/exit hop used to be plugged (almost) directly into the sphinx package’s observation of 32 all 0x00-bytes for the onion HMAC. Somewhere along the line the condition which defines whether a node is the final/exit hop appears to have changed from 32 0x00-bytes for the onion HMAC to an empty short_channel_id in the top level onion TLV payload. It looks like things may have changed w.r.t determining the final/exit hop when moving TLV onion payloads? - https://github.com/lightningnetwork/lnd/blob/23cc8389f2e7db968e859f2ee2426b0906c2dd5d/htlcswitch/iterator_test.go#L78-L79 We will return to the old days where the sphinx implementation encountering an all-zero 32 byte onion HMAC signals we are the final hop. We can no longer rely on the presence of a next_hop in the top level onion TLV payload as it will not be there for blinded hops.
The ChannelLink must have access to our persistent node ID key in order to process hops in a blinded route. TODO(9/20/22): Ensure that we do not undo the hardwork done to tighten up signing abstractions and remove all raw private key handling in: lightningnetwork#3929
Add the ephemeral (route) blinding point as a TLV extension to the UpdateAddHTLC message. If an HTLC has an ephemeral blinding point, it will be needed to decrypt the onion as the onion encryptor is expected to have encrypted the onion to a blinded form of our node ID, rather than to our persistent node ID.
This places the route blinding point in our in-memory update log, so it is available for use during onion & route blinding payload decryption for nodes inside a blinded route. The blinding point may also be used to determine how errors, both local and downstream, will be processed. A forwarding node has two channel links involved in forwarding an HTLC, both of which have their own update logs, payment descriptors, & channel state machines. When an HTLC is forwarded, it is received and added to a remote update log by the incoming link and added to a local update log prior to commitment by the outgoing link. If we would like the channel state machine to preserve whether or not the HTLC had an ephemeral blinding point, then the blinding point must be looked after in both locations. TODO(11/21/22): - When processing a failure, the HTLC flows through the switch in the opposite direction. We need to decide which link will handle determining how errors are to be forwarded. Consider HTLC update retransmission (in-memory and from disk) code path. It seems to me we have two types of retransmission: - In memory retransmission (ie: our node had an internal error processing the HTLC update, or our peer restarted) - From disk retransmission (ie: our link/switch/node restarted - power outage, crashed due to bug, etc.) We will need to make sure that HTLC updates (adds, settle, fails) for blind hops are processed correctly after a restart.
Define an opaque (non-privacy-leaking) error type which is to be used ubiquitously for errors which occur inside a blinded route regardless of the internal or downstream reason for failure.
We can no longer perform the totality of the validation when the onion TLV payload is parsed. The validation we perform depends on the contents of the top level onion TLV payload, the route blinding payload, and the UpdateAddHTLC message.
Equip the channel link to process HTLCs inside a blinded route. The link will decrypt and parse the route blinding payload, use data from the payload to make a forwarding "decision", and compute the ephemeral (route) blinding point for the next hop in route.
This is still a work in progress. Go over error handling with a microscope as apparently it is fraught with danger.
allow a user to specify whether they would like to enable the HTLCSwitch to process HTLCs on a blind route
…ind hops We expand the capability of the mockHopIterator such that it is able to handle both normal and blind hops. The destinction is made via a check for sentinel value which delineates the byte boundary between serialized hops. The implemenation is functional yet somewhat propietary in the sense that it is specific to handling blind hops and not as general as it could be. This lack of generality leaves the door open to eventual inclusion of the full blown TLV serialization scheme into the mock iterator. Without this or something like TLV we do not have a way to know whether we should or even how to deserialize a variable length field like the route blinding payload.
Add several test cases which verify that the link supports route blinding. More specifically we verify that the ChannelLink can process an onion packet "sent" to a blinded node ID public key rather than the usual persistent node ID public key, unblind the next hop in the route and forward the HTLC. We also verify that a ChannelLink processing a blind hop returns the opaque InvalidOnionBlinding error under the expected scenarios. This provides assurance that would be probers will always receive the same (hopefully) opaque/non-privacy leaking error message regardless of the internal reason for failure. It also provides indirect assurance that the Link is actually validating the blind hop as specified by BOLT-04!!
Submitting on the off chance that no-one has a branch which does this yet. If someone already has an implementation, I can consider this a knowledge-accumulating attempt to get the conversation rolling for route blinding on LND, close this one out, and try to provide competent review when the official LL PR drops. Looking forward to it. Thanks! |
Super exciting to see somebody working on this 🚀 I'm about half-way through working on forwarding blinded routes here, but it's not as advanced as this PR! Need to take a better look at your approach, but would be interested to chat about collaborating on this. Going to ping you on LND slack to figure out the best way to communicate :) |
Oops, forgot to comment on this, thanks for getting things going here @calvinrzachman! We have some lofty plans in progress to get a form of blinded paths that supports forwarding and receiving/sending independent on the invoicing mechanism used in time for lnd 0.17. At the current pace, this would mean a release sometime in Spring 2023. |
This (definitely draft) PR equips the
ChannelLink
to process HTLCs inside a blinded route. The bulk of the processing for blind hops in done by the incoming link (ie: the link on which the HTLC ADD arrives). The incoming link will:The outgoing link simply needs to forward the UpdateAddHTLC message it is given by the Switch. Everything will have been assembled for successful forwarding by the incoming link.
TODO: Several branches are still far too dirty to post publicly. Clean up branches for following:
Comments
As of now this PR punts on dummy hop processing, integrating blinded routes with invoices, an algorithm for selecting the introduction node, and automated blinded route pathfinding. With this PR alone, LND won't be able to create or receive payment over a blinded route just yet, but it will be available for others to use while building blinded routes. Last I heard, a large portion of nodes on the network run LND, so even this modest start to an implementation could provide a boon to anonymity set sizes.
I tried to split things up such that the things I left out would not, if considered, fundamentally change the approach, though lacking a complete knowledge of BOLT-12 or Trampoline Routing, it is very possible that I did not succeed in this.
The route-blinding spec is still a living document, so I may be behind on some of the recent updates, particularly those on error handling. There is also a fair bit of cleanup left to do - far more than I would like for posting this at present - but after reading this, I wanted to get this up sooner and get some information on where Lightning Labs is at in this area before spending too much more time deep in the weeds.
Steps to Test
htlcswitch
package level.itest
level which sets up a linear networkAlice <---> Bob <---> Carol <---> Dave
, creates a blinded route via RPC, concatenates the route to a normalroute.Route{}
and then verifies that payment can be sent successfully. Can post once it's a bit cleaner.Pull Request Checklist
Testing
Code Style and Documentation
[skip ci]
in the commit message for small changes.📝 Please see our Contribution Guidelines for further guidance.