multi: endpoints for onion 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.
This commit is contained in:
Gijs van Dam authored and yyforyongyu committed 2025-11-12 22:54:04 +08:00
1 parent 2ee0702942
commit 07dc74e198
9 files changed
+398

No files matched your search

+79
View File
@@ -70,6 +70,7 @@ import (
"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/onionmessage"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/peer"
"github.com/lightningnetwork/lnd/peernotifier"
@@ -573,6 +574,14 @@ func MainRPCServerPermissions() map[string][]bakery.Op {
Entity: "offchain",
Action: "read",
}},
"/lnrpc.Lightning/SendOnionMessage": {{
Entity: "offchain",
Action: "write",
}},
"/lnrpc.Lightning/SubscribeOnionMessages": {{
Entity: "offchain",
Action: "read",
}},
"/lnrpc.Lightning/LookupHtlcResolution": {{
Entity: "offchain",
Action: "read",
@@ -9301,6 +9310,76 @@ func (r *rpcServer) SubscribeCustomMessages(
}
}
// SendOnionMessage sends a custom peer message.
func (r *rpcServer) SendOnionMessage(ctx context.Context,
req *lnrpc.SendOnionMessageRequest) (*lnrpc.SendOnionMessageResponse,
error) {
// First we'll validate the string passed in within the request to
// ensure that it's a valid hex-string, and also a valid compressed
// public key.
pathKey, err := btcec.ParsePubKey(req.PathKey)
if err != nil {
return nil, fmt.Errorf("unable to decode path key bytes: %w",
err)
}
peer, err := route.NewVertexFromBytes(req.Peer)
if err != nil {
return nil, err
}
err = r.server.SendOnionMessage(ctx, peer, pathKey, req.Onion)
switch {
case errors.Is(err, ErrPeerNotConnected):
return nil, status.Error(codes.NotFound, err.Error())
case err != nil:
return nil, err
}
return &lnrpc.SendOnionMessageResponse{
Status: "onion message sent successfully",
}, nil
}
// SubscribeOnionMessages subscribes to a stream of incoming onion messages.
func (r *rpcServer) SubscribeOnionMessages(
_ *lnrpc.SubscribeOnionMessagesRequest,
server lnrpc.Lightning_SubscribeOnionMessagesServer) error {
client, err := r.server.SubscribeOnionMessages()
if err != nil {
return err
}
defer client.Cancel()
for {
select {
case <-client.Quit():
return errors.New("shutdown")
case <-server.Context().Done():
return server.Context().Err()
case update := <-client.Updates():
oMsg, ok := update.(*onionmessage.OnionMessageUpdate)
if !ok {
return fmt.Errorf("onion message update "+
"failed type assertion: %T", update)
}
err := server.Send(&lnrpc.OnionMessage{
Peer: oMsg.Peer[:],
PathKey: oMsg.PathKey[:],
Onion: oMsg.OnionBlob,
})
if err != nil {
return err
}
}
}
}
// ListAliases returns the set of all aliases we have ever allocated along with
// their base SCIDs and possibly a separate confirmed SCID in the case of
// zero-conf.