-
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
[feature]: Blinded Forwarding in LND #7298
Comments
@calvinrzachman and I are working on an updated verion of #7195 to address this! Since it's a larger change, we're looking to break it up into parts:
-> Would appreciate some feedback from the LL team if this breakdown would work/ other suggestions if desired! |
Thanks for such a clear proposal!
One thing I've reaaally been meaning to do over the year is: get rid of the mega Here's a mega old commit fragment from an abandoned branch (early flavor of dynamic commitments) if you'd like to pick up the task: Roasbeef@16d036e#diff-8896f76f365f8d3c7b6aec4e89140c923aeaf5a5ec1487b9c6cb9fd37cf5cab7R13-R34.
I think the migration has the potential to be pretty painless, given an active node should only have a hand full of active HTLC resolvers. This may also be useful for some of the taproot work as well, since these resolvers now either need to recompute the tapscript inclusion proof, or they can just grab the fully encoded control block from disk. |
This issue outlines a proposal for adding support for forwarding payments in blinded routes. Receiving payments via blinded routes is out of scope for this issue.
Parent: #5594
Related: #7200 + #7267
Background
Nodes that support forwarding blinded payments in the Lightning Network need to perform some additional tasks to help forward payments to an obfuscated destination. There are two different roles that a node in a blinded path can play in blinded forwarding:
For easy reference, the difference between these two nodes is as follows:
Introduction Node
The introduction node acts as a bridge between the unblinded and blinded portions of the route. It processes payments in a blinded route in the following sequence:
update_add_htlc
message with onion payloadblinding_point
andencrypted_data
TLVsencrypted_data
encrypted_data
payloadupdate_add_htlc
with next blinding point inblinding_point
TLVRelaying Node
A relaying node receives an update_add_htlc message with a blinding point TLV included, which is used to decrypt the onion. It processed payments in a blinded route with the following sequence:
update_add_htlc
message with onion payload and blinding_point TLVblinding_point
to decrypt onionblinding_point
to decrypt itencrypted_data
payloadupdate_add_htlc
with next blinding point inblinding_point
TLVImplementation
Processing HTLCs
The link is our first point of contact with HTLCs that will need to be updated to accommodate HTLCs in blinded routes. At a high level, the incoming link will need to:
The outgoing link will simply need to forward an UpdateAddHTLC to the next peer including the next blinding point. In the case of a payment success, there is no additional handling required for HTLCs that are relayed within a blinded route.
Payments that are included in blinded routes also require custom error handling, because the errors need to be generated using the blinding point tweaked ephemeral key. The introduction and relay nodes in a blinded route also handle errors differently to prevent probing, so we need to be aware of our position in the blinded route to relay errors in a spec-compliant way:
Restarts
As outlined in #7297, once a HTLC is irrevocably committed to both parties' commitments, we only have it stored as a channeldb.HTLC in our state machine. Assuming that we do not want to migrate channeldb.HTLC, we employ the following workarounds to ensure that we always have the blinding point for the HTLC available.
Workaround 1: Restore Blinding Point Pending Remote Updates
If we restart when an incoming HTLC is irrevocably committed to our local commit, but has not yet been added to the remote peer’s commitment, we will not have the blinding point populated in our remote update log (see “Irrevocably committed by the receiver” in #7297). This HTLC still needs its blinding_point to be able to forward correctly to the outgoing peer, so we supplement the remoteUpdateLog with our pending remote updates (which still have the full wire message stored).
Workaround 2: Store Blinding Point in Error Encryptor
The ErrorEncryptor interface that is used to encrypt HTLC errors is currently provided by the SphinxErrorEncryptor implementation. Encoding and decoding of the error encryptor is paired with a type, which allows us to easily extend our persistence to store a blinding point along with the obfuscator to ensure that we use the correct shared secret for error obfuscation.
On-Chain Resolution
We also make use of channeldb.HTLC in our incomingContestResolver where we will need the HTLC’s blinding point to ReconstructHopIterator when we decode our payload. The embedded htlcSuccessResolver that contains this HTLC already has an “ad-hoc” migration where we try to read more bytes out of the bucket, then fail if they’re not present. We can either look at a migration for the resolver, or add another ad-hoc field at the end to include the blinding point.
The text was updated successfully, but these errors were encountered: