-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Onion message forwarding #10089
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
base: master
Are you sure you want to change the base?
Onion message forwarding #10089
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.
Summary of Changes
Hello @gijswijs, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request introduces the foundational functionality for forwarding onion messages within the Lightning Network. It integrates a new OnionMessage
wire protocol message, enables its routing through the existing Sphinx onion processing infrastructure, and provides RPC endpoints for sending and subscribing to these messages. This work lays the groundwork for future application-layer protocols like BOLT12 offers, allowing for privacy-preserving communication beyond just payments.
Highlights
- Onion Message Wire Protocol: Introduces a new
lnwire.OnionMessage
type to the wire protocol, enabling the transmission of onion-encrypted messages between Lightning Network nodes. This message type is distinct from HTLC-carrying onion packets and is designed for application-layer communication. - Sphinx Onion Processing Integration: Extends the existing Sphinx onion processing logic within
htlcswitch/hop
to correctly parse and handleOnionMessage
payloads. This includes adapting the hop iterator to recognize onion messages, extracting forwarding information (such as theNextNodeID
for node-based routing), and performing message-specific TLV validations. - New RPC Endpoints for Onion Messages: Adds
SendOnionMessage
andSubscribeOnionMessages
to the LND RPC API. These new endpoints allow external applications and users to programmatically send onion messages to peers and subscribe to a stream of incoming onion messages, facilitating the development of new privacy-preserving communication features. - Dedicated Message Endpoint and Forwarding Logic: Implements a new
onion_message.OnionEndpoint
that integrates with themsgmux
to process incominglnwire.OnionMessage
s. This endpoint is responsible for decrypting the onion blob, determining if the message is for the local node or needs forwarding, and then either dispatching it to subscribers or relaying it to the next hop in the blinded path. - Enhanced Blinded Path Handling: Introduces specific logic for blinded paths within onion messages, including the addition of
NextNodeID
toForwardingInfo
. This ensures that onion messages, which do not carry payment-related information like CLTV deltas or amounts, are correctly processed and forwarded along their intended blinded routes.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
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.
Code Review
This pull request introduces onion message forwarding, a significant feature that touches multiple parts of the codebase. The changes are generally well-structured, with new functionality encapsulated in the onion_message
package and corresponding updates to lnwire
, htlcswitch
, and the RPC layer. The inclusion of integration tests for both direct and forwarded onion messages is a great addition. I've identified a few issues that need attention: a critical bug in handling dummy hops for onion messages, a high-severity issue with TLV decoding that could lead to panics, and a medium-severity issue regarding message routing logic that could cause confusion and potential bugs. Addressing these will improve the correctness and maintainability of the new functionality.
9157266
to
83a36aa
Compare
83a36aa
to
4de5d9e
Compare
4de5d9e
to
953b2d8
Compare
This message type is a message that carries an onion-encrypted payload used for BOLT12 messages.
This commit creates the necessary endpoints for onion messages. Specifically, it adds the following: - `SendOnionMessage` endpoint to send onion messages. - `SubscribeOnionMessages` endpoint to subscribe to incoming onion messages. It uses the `msgmux` package to handle the onion messages.
953b2d8
to
3f475ce
Compare
The new wire message defines the OnionMessagePayload, FinalHopPayload, ReplyPath, and related TLV encoding/decoding logic.
Use fork github.com/gijswijs/lightning-onion at commit fac332540872 to include onion-messaging support before the upstream PR is merged. This temporary replace in go.mod ensures compatibility with the current module path while allowing local development and CI to build with the new functionality.
With this commit we implement the logic to parse, decrypt, and forward onion messages. It contains a refactor to its constructor to accept dependencies like the onionProcessor and a message sender function. In brontide.go and server.go it adds the plumbing to for passing through the onionProcessor from the hop iterator and the SendOnionMessage function to the OnionEndpoint's constructor.
Adds the NewNonFinalBlindedRouteDataOnionMessage function to create blinded route data specifically for onion messages.
With this Update we change the SubscribeOnionMessages RPC to return a stream of OnionMessageUpdate messages instead of OnionMessage. This way we also send back the decrypted payload if any, so we can inspect that in itests.
Adds the new integration test file to test forwarding of onion messages through a multi-hop path.
3f475ce
to
606d9e5
Compare
// NextNodeID is the public key of the next node in the route. This is | ||
// used by onion messages that do not necessarily care about the channel | ||
// ID. | ||
NextNodeID *btcec.PublicKey |
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 we need to add this to the existing HTLC forwarding fabric at all. The only thing we care about for now is that we have a channel between the target peer (see my proposal on how we can lift this requirement).
In other words, we can make this a competely stand alone sub-system, using the actor
package.
I described this in another PR, but we'd have two actors:
- the processor:
- In the
readHandler
, we read each onion message off the wire, then send it to the proecssor. - The processor takes the onion message, and transform it to figure out where to send it next. It sends it to an onion endpoint for each peer.
- In the
- The onion endpoint:
- When a peer connects, we make an instance of this actor, but only if it has the feature bit.
- It just takes in the incoming message, and sends the onion message to the direct peer, via an interface.
|
||
// isOnionMessage is a flag that indicates whether the iterator is for | ||
// an onion message. | ||
isOnionMessage bool |
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.
Same here, generally I think we can reduce the invasiveness of this diff, and make it much easier to review with my suggestion above.
return nil, routeRole, err | ||
} | ||
if !isOnionMessage { | ||
relayInfo, err := routeData.RelayInfo.UnwrapOrErr( |
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.
Yep, we wouldn't need to tangle with this code at all, just slightly duplicating the existing blinded paths processing code.
}, | ||
} | ||
|
||
resps, err := o.onionProcessor.DecodeHopIterators( |
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.
IIUC, this'll also actually cause us to hit disk for replay protection. Thinking about it a bit more: is any replay protection even defined for onion messaging?
// forwarding information for an onion message. It contains either | ||
// next_node_id or short_channel_id for each non-final node. It MAY contain | ||
// the path_id for the final node. | ||
bytes encrypted_recipient_data = 5; |
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.
If this is intended for users to consume, shouldn't this be decrypted?
OnionMessageServer *subscribe.Server | ||
|
||
// OnionMsgSender is a function that sends an onion message to any peer. | ||
OnionMsgSender func([33]byte, *btcec.PublicKey, []byte) error |
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.
Why do we need this vs just the existing SendMessage
method we have? It can submit just the dest and the wire message.
@gijswijs, remember to re-request review from reviewers when ready |
With this PR we add basic forwarding functionality for onion messages. It builds on PR #9868.
It adds
OnionMessagePayload
struct to thelnwire
package.It also depends on the not yet merged (PR 68)[https://github.com/lightningnetwork/lightning-onion/pull/68] in the
lightning-onion
package. For now it uses that package from a forked version.The
msgmux
endpoint for onion messages is updated to parse the onion message packet, and forward the onion based on the acquired information.The
SubscribeOnionMessages
endpoint is updated to pass along any decrypted information. This endpoint is currently solely meant for itests, although it could have practical use in the future.