@@ -10,6 +10,8 @@ import (
1010
1111 "github.com/btcsuite/btcd/btcec/v2"
1212 "github.com/btcsuite/btclog/v2"
13+ "github.com/lightningnetwork/lnd/actor"
14+ "github.com/lightningnetwork/lnd/fn/v2"
1315 "github.com/lightningnetwork/lnd/htlcswitch/hop"
1416 "github.com/lightningnetwork/lnd/lnutils"
1517 "github.com/lightningnetwork/lnd/lnwire"
@@ -48,11 +50,64 @@ var (
4850 ErrNoNextNodeID = errors .New ("next node ID required" )
4951)
5052
51- // OnionMessageSender is a function type that defines how to send an onion
52- // message. It takes the next node's public key (as [33]byte), the blinding
53- // point (*btcec.PublicKey), and the onion packet ([]byte) to send to a peer.
54- type OnionMessageSender func (context.Context , [33 ]byte , * btcec.PublicKey ,
55- []byte ) error
53+ type OMRequest struct {
54+ // Embed BaseMessage to satisfy the Message interface.
55+ actor.BaseMessage
56+ msg lnwire.OnionMessage
57+ }
58+
59+ // MessageType returns a string identifier for this message type.
60+ func (m * OMRequest ) MessageType () string {
61+ return "OnionMessageRequest"
62+ }
63+
64+ // MyResponse might be a corresponding response type.
65+ type OMResponse struct {
66+ actor.BaseMessage
67+ Success bool
68+ }
69+
70+ func (m * OMResponse ) MessageType () string {
71+ return "OnionMessageResponse"
72+ }
73+
74+ type OnionPeerActorRef actor.ActorRef [* OMRequest , * OMResponse ]
75+
76+ // PeerOnionSenderKey returns the actor key used to send onion messages to a
77+ // specific peer identified by their public key.
78+ func SpawnOnionPeerActor (system * actor.ActorSystem ,
79+ sender func (msg * lnwire.OnionMessage ),
80+ pubKey [33 ]byte ) OnionPeerActorRef {
81+
82+ // The actor logic creates a function behavior that sends onion messages
83+ // using the provided sender function.
84+ actorLogic := func (ctx context.Context ,
85+ req * OMRequest ) fn.Result [* OMResponse ] {
86+
87+ select {
88+ case <- ctx .Done ():
89+ return fn.Err [* OMResponse ](
90+ errors .New ("actor shutting down" ),
91+ )
92+ default :
93+ }
94+
95+ sender (& req .msg )
96+ response := & OMResponse {Success : true }
97+ return fn .Ok (response )
98+ }
99+
100+ // Create a behavior from the function.
101+ behavior := actor .NewFunctionBehavior (actorLogic )
102+
103+ pubKeyHex := hex .EncodeToString (pubKey [:])
104+ serviceKey := actor.NewServiceKey [* OMRequest , * OMResponse ](pubKeyHex )
105+ actorRef := serviceKey .Spawn (
106+ system , "onion-peer-actor-" + pubKeyHex , behavior ,
107+ )
108+
109+ return actorRef
110+ }
56111
57112// OnionMessageUpdate is onion message update dispatched to any potential
58113// subscriber.
@@ -89,13 +144,6 @@ func WithMessageServer(server *subscribe.Server) OnionEndpointOption {
89144 }
90145}
91146
92- // WithMessageSender sets the onion message sender for the OnionEndpoint.
93- func WithMessageSender (msgSender OnionMessageSender ) OnionEndpointOption {
94- return func (o * OnionEndpoint ) {
95- o .MsgSender = msgSender
96- }
97- }
98-
99147// WithOnionProcessor sets the onion processor for the OnionEndpoint.
100148func WithOnionProcessor (processor * hop.OnionProcessor ) OnionEndpointOption {
101149 return func (o * OnionEndpoint ) {
@@ -111,18 +159,19 @@ type OnionEndpoint struct {
111159 // onionProcessor is the onion processor used to process onion packets.
112160 onionProcessor * hop.OnionProcessor
113161
114- // MsgSender sends a onion message to the target peer.
115- MsgSender OnionMessageSender
162+ // receptionist is the actor system receptionist used to look up peer
163+ // onion actors.
164+ receptionist * actor.Receptionist
116165}
117166
118167// A compile-time check to ensure OnionEndpoint implements the Endpoint
119168// interface.
120169var _ msgmux.Endpoint = (* OnionEndpoint )(nil )
121170
122171// NewOnionEndpoint creates a new OnionEndpoint with the given options.
123- func NewOnionEndpoint (opts ... OnionEndpointOption ) * OnionEndpoint {
172+ func NewOnionEndpoint (receptionist * actor. Receptionist , opts ... OnionEndpointOption ) * OnionEndpoint {
124173 o := & OnionEndpoint {
125- onionMessageServer : nil ,
174+ receptionist : receptionist ,
126175 }
127176 for _ , opt := range opts {
128177 opt (o )
@@ -283,12 +332,26 @@ func (o *OnionEndpoint) forwardMessage(ctx context.Context,
283332 var nextNodeIDBytes [33 ]byte
284333 copy (nextNodeIDBytes [:], nextNodeID .SerializeCompressed ())
285334
286- err := o .MsgSender (
287- ctx , nextNodeIDBytes , nextBlindingPoint , nextPacket ,
288- )
289-
290- if err != nil {
291- return fmt .Errorf ("could not send message: %w" , err )
335+ // err := o.MsgSender(
336+ // ctx, nextNodeIDBytes, nextBlindingPoint, nextPacket,
337+ // )
338+
339+ // Find the onion peer actor for the next node ID.
340+ pubKeyHex := hex .EncodeToString (nextNodeIDBytes [:])
341+ serviceKey := actor.NewServiceKey [* OMRequest , * OMResponse ](pubKeyHex )
342+ foundActorRefs := actor .FindInReceptionist (o .receptionist , serviceKey )
343+
344+ // If we found an actor, send the onion message to it.
345+ if len (foundActorRefs ) > 0 {
346+ actorRef := foundActorRefs [0 ]
347+ onionMsg := lnwire .NewOnionMessage (
348+ nextBlindingPoint , nextPacket ,
349+ )
350+ req := & OMRequest {msg : * onionMsg }
351+ actorRef .Tell (ctx , req )
352+ } else {
353+ return fmt .Errorf ("No actors found for service key: %v" ,
354+ serviceKey )
292355 }
293356
294357 return nil
0 commit comments