@@ -54,6 +54,21 @@ type Manager struct {
5454 cfg * ManagerConfig
5555
5656 currentHeight atomic.Int32
57+
58+ // addrRequest is a channel used to request new static addresses from
59+ // the manager. The manager employs a go worker routine that handles the
60+ // requests.
61+ addrRequest chan request
62+ }
63+
64+ type request struct {
65+ ctx context.Context
66+ respChan chan response
67+ }
68+
69+ type response struct {
70+ parameters * Parameters
71+ err error
5772}
5873
5974// NewManager creates a new address manager.
@@ -64,14 +79,48 @@ func NewManager(cfg *ManagerConfig, currentHeight int32) (*Manager, error) {
6479 }
6580
6681 m := & Manager {
67- cfg : cfg ,
82+ cfg : cfg ,
83+ addrRequest : make (chan request ),
6884 }
6985 m .currentHeight .Store (currentHeight )
7086
7187 return m , nil
7288}
7389
74- // Run runs the address manager.
90+ // addrWorker is a worker that handles address creation requests. It calls
91+ // m.newAddress which blocks on server I/O and returns the address and expiry.
92+ func (m * Manager ) addrWorker (ctx context.Context ) {
93+ for {
94+ select {
95+ case req := <- m .addrRequest :
96+ m .handleAddrRequest (ctx , req )
97+
98+ case <- ctx .Done ():
99+ return
100+ }
101+ }
102+ }
103+
104+ // handleAddrRequest is responsible for processing a single address request.
105+ func (m * Manager ) handleAddrRequest (managerCtx context.Context , req request ) {
106+ addrParams , err := m .newAddress (req .ctx )
107+
108+ resp := response {
109+ parameters : addrParams ,
110+ err : err ,
111+ }
112+
113+ select {
114+ case req .respChan <- resp :
115+
116+ case <- req .ctx .Done ():
117+
118+ case <- managerCtx .Done ():
119+ }
120+ }
121+
122+ // Run runs the address manager. It keeps track of the current block height and
123+ // creates new static addresses as needed.
75124func (m * Manager ) Run (ctx context.Context , initChan chan struct {}) error {
76125 newBlockChan , newBlockErrChan , err :=
77126 m .cfg .ChainNotifier .RegisterBlockEpochNtfn (ctx )
@@ -80,6 +129,10 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
80129 return err
81130 }
82131
132+ // The address worker offloads the address creation with the server to a
133+ // separate go routine.
134+ go m .addrWorker (ctx )
135+
83136 // Communicate to the caller that the address manager has completed its
84137 // initialization.
85138 close (initChan )
@@ -100,49 +153,64 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
100153}
101154
102155// NewAddress creates a new static address with the server or returns an
103- // existing one.
104- func (m * Manager ) NewAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
105- int64 , error ) {
156+ // existing one. It now sends a request to the manager's Run loop which
157+ // executes the actual address creation logic.
158+ func (m * Manager ) NewAddress (ctx context.Context ) (* Parameters , error ) {
159+ respChan := make (chan response , 1 )
160+ req := request {
161+ ctx : ctx ,
162+ respChan : respChan ,
163+ }
164+
165+ // Send the new address request to the manager run loop.
166+ select {
167+ case m .addrRequest <- req :
106168
169+ case <- ctx .Done ():
170+ return nil , ctx .Err ()
171+ }
172+
173+ // Wait for the response from the manager run loop.
174+ select {
175+ case resp := <- respChan :
176+ return resp .parameters , resp .err
177+
178+ case <- ctx .Done ():
179+ return nil , ctx .Err ()
180+ }
181+ }
182+
183+ // newAddress contains the body of the former NewAddress method and performs the
184+ // actual address creation/lookup according to the requested type.
185+ func (m * Manager ) newAddress (ctx context.Context ) (* Parameters , error ) {
107186 // If there's already a static address in the database, we can return
108187 // it.
109188 m .Lock ()
110189 addresses , err := m .cfg .Store .GetAllStaticAddresses (ctx )
111190 if err != nil {
112191 m .Unlock ()
113192
114- return nil , 0 , err
193+ return nil , err
115194 }
116195 if len (addresses ) > 0 {
117- clientPubKey := addresses [0 ].ClientPubkey
118- serverPubKey := addresses [0 ].ServerPubkey
119- expiry := int64 (addresses [0 ].Expiry )
120-
121- defer m .Unlock ()
122-
123- address , err := m .GetTaprootAddress (
124- clientPubKey , serverPubKey , expiry ,
125- )
126- if err != nil {
127- return nil , 0 , err
128- }
196+ m .Unlock ()
129197
130- return address , expiry , nil
198+ return addresses [ 0 ] , nil
131199 }
132200 m .Unlock ()
133201
134202 // We are fetching a new L402 token from the server. There is one static
135203 // address per L402 token allowed.
136204 err = m .cfg .FetchL402 (ctx )
137205 if err != nil {
138- return nil , 0 , err
206+ return nil , err
139207 }
140208
141209 clientPubKey , err := m .cfg .WalletKit .DeriveNextKey (
142210 ctx , swap .StaticAddressKeyFamily ,
143211 )
144212 if err != nil {
145- return nil , 0 , err
213+ return nil , err
146214 }
147215
148216 // Send our clientPubKey to the server and wait for the server to
@@ -155,27 +223,27 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
155223 },
156224 )
157225 if err != nil {
158- return nil , 0 , err
226+ return nil , err
159227 }
160228
161229 serverParams := resp .GetParams ()
162230
163231 serverPubKey , err := btcec .ParsePubKey (serverParams .ServerKey )
164232 if err != nil {
165- return nil , 0 , err
233+ return nil , err
166234 }
167235
168236 staticAddress , err := script .NewStaticAddress (
169237 input .MuSig2Version100RC2 , int64 (serverParams .Expiry ),
170238 clientPubKey .PubKey , serverPubKey ,
171239 )
172240 if err != nil {
173- return nil , 0 , err
241+ return nil , err
174242 }
175243
176244 pkScript , err := staticAddress .StaticAddressScript ()
177245 if err != nil {
178- return nil , 0 , err
246+ return nil , err
179247 }
180248
181249 // Create the static address from the parameters the server provided and
@@ -196,7 +264,7 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
196264 }
197265 err = m .cfg .Store .CreateStaticAddress (ctx , addrParams )
198266 if err != nil {
199- return nil , 0 , err
267+ return nil , err
200268 }
201269
202270 // Import the static address tapscript into our lnd wallet, so we can
@@ -206,20 +274,13 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
206274 )
207275 addr , err := m .cfg .WalletKit .ImportTaprootScript (ctx , tapScript )
208276 if err != nil {
209- return nil , 0 , err
277+ return nil , err
210278 }
211279
212280 log .Infof ("Imported static address taproot script to lnd wallet: %v" ,
213281 addr )
214282
215- address , err := m .GetTaprootAddress (
216- clientPubKey .PubKey , serverPubKey , int64 (serverParams .Expiry ),
217- )
218- if err != nil {
219- return nil , 0 , err
220- }
221-
222- return address , int64 (serverParams .Expiry ), nil
283+ return addrParams , nil
223284}
224285
225286// GetTaprootAddress returns a taproot address for the given client and server
0 commit comments