@@ -54,19 +54,68 @@ 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.
6075func NewManager (cfg * ManagerConfig , currentHeight int32 ) * Manager {
6176 m := & Manager {
62- cfg : cfg ,
77+ cfg : cfg ,
78+ addrRequest : make (chan request ),
6379 }
6480 m .currentHeight .Store (currentHeight )
6581
6682 return m
6783}
6884
69- // Run runs the address manager.
85+ // addrWorker is a worker that handles address creation requests. It calls
86+ // m.newAddress which blocks on server I/O and returns the address and expiry.
87+ func (m * Manager ) addrWorker (ctx context.Context ) {
88+ for {
89+ select {
90+ case req := <- m .addrRequest :
91+ m .handleAddrRequest (ctx , req )
92+
93+ case <- ctx .Done ():
94+ return
95+ }
96+ }
97+ }
98+
99+ // handleAddrRequest is responsible for processing a single address request.
100+ func (m * Manager ) handleAddrRequest (managerCtx context.Context , req request ) {
101+ addrParams , err := m .newAddress (req .ctx )
102+
103+ resp := response {
104+ parameters : addrParams ,
105+ err : err ,
106+ }
107+
108+ select {
109+ case req .respChan <- resp :
110+
111+ case <- req .ctx .Done ():
112+
113+ case <- managerCtx .Done ():
114+ }
115+ }
116+
117+ // Run runs the address manager. It keeps track of the current block height and
118+ // creates new static addresses as needed.
70119func (m * Manager ) Run (ctx context.Context , initChan chan struct {}) error {
71120 newBlockChan , newBlockErrChan , err :=
72121 m .cfg .ChainNotifier .RegisterBlockEpochNtfn (ctx )
@@ -75,6 +124,10 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
75124 return err
76125 }
77126
127+ // The address worker offloads the address creation with the server to a
128+ // separate go routine.
129+ go m .addrWorker (ctx )
130+
78131 // Communicate to the caller that the address manager has completed its
79132 // initialization.
80133 close (initChan )
@@ -95,49 +148,64 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
95148}
96149
97150// NewAddress creates a new static address with the server or returns an
98- // existing one.
99- func (m * Manager ) NewAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
100- int64 , error ) {
151+ // existing one. It now sends a request to the manager's Run loop which
152+ // executes the actual address creation logic.
153+ func (m * Manager ) NewAddress (ctx context.Context ) (* Parameters , error ) {
154+ respChan := make (chan response , 1 )
155+ req := request {
156+ ctx : ctx ,
157+ respChan : respChan ,
158+ }
159+
160+ // Send the new address request to the manager run loop.
161+ select {
162+ case m .addrRequest <- req :
101163
164+ case <- ctx .Done ():
165+ return nil , ctx .Err ()
166+ }
167+
168+ // Wait for the response from the manager run loop.
169+ select {
170+ case resp := <- respChan :
171+ return resp .parameters , resp .err
172+
173+ case <- ctx .Done ():
174+ return nil , ctx .Err ()
175+ }
176+ }
177+
178+ // newAddress contains the body of the former NewAddress method and performs the
179+ // actual address creation/lookup according to the requested type.
180+ func (m * Manager ) newAddress (ctx context.Context ) (* Parameters , error ) {
102181 // If there's already a static address in the database, we can return
103182 // it.
104183 m .Lock ()
105184 addresses , err := m .cfg .Store .GetAllStaticAddresses (ctx )
106185 if err != nil {
107186 m .Unlock ()
108187
109- return nil , 0 , err
188+ return nil , err
110189 }
111190 if len (addresses ) > 0 {
112- clientPubKey := addresses [0 ].ClientPubkey
113- serverPubKey := addresses [0 ].ServerPubkey
114- expiry := int64 (addresses [0 ].Expiry )
115-
116- defer m .Unlock ()
117-
118- address , err := m .GetTaprootAddress (
119- clientPubKey , serverPubKey , expiry ,
120- )
121- if err != nil {
122- return nil , 0 , err
123- }
191+ m .Unlock ()
124192
125- return address , expiry , nil
193+ return addresses [ 0 ] , nil
126194 }
127195 m .Unlock ()
128196
129197 // We are fetching a new L402 token from the server. There is one static
130198 // address per L402 token allowed.
131199 err = m .cfg .FetchL402 (ctx )
132200 if err != nil {
133- return nil , 0 , err
201+ return nil , err
134202 }
135203
136204 clientPubKey , err := m .cfg .WalletKit .DeriveNextKey (
137205 ctx , swap .StaticAddressKeyFamily ,
138206 )
139207 if err != nil {
140- return nil , 0 , err
208+ return nil , err
141209 }
142210
143211 // Send our clientPubKey to the server and wait for the server to
@@ -150,27 +218,27 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
150218 },
151219 )
152220 if err != nil {
153- return nil , 0 , err
221+ return nil , err
154222 }
155223
156224 serverParams := resp .GetParams ()
157225
158226 serverPubKey , err := btcec .ParsePubKey (serverParams .ServerKey )
159227 if err != nil {
160- return nil , 0 , err
228+ return nil , err
161229 }
162230
163231 staticAddress , err := script .NewStaticAddress (
164232 input .MuSig2Version100RC2 , int64 (serverParams .Expiry ),
165233 clientPubKey .PubKey , serverPubKey ,
166234 )
167235 if err != nil {
168- return nil , 0 , err
236+ return nil , err
169237 }
170238
171239 pkScript , err := staticAddress .StaticAddressScript ()
172240 if err != nil {
173- return nil , 0 , err
241+ return nil , err
174242 }
175243
176244 // Create the static address from the parameters the server provided and
@@ -191,7 +259,7 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
191259 }
192260 err = m .cfg .Store .CreateStaticAddress (ctx , addrParams )
193261 if err != nil {
194- return nil , 0 , err
262+ return nil , err
195263 }
196264
197265 // Import the static address tapscript into our lnd wallet, so we can
@@ -201,20 +269,13 @@ func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot,
201269 )
202270 addr , err := m .cfg .WalletKit .ImportTaprootScript (ctx , tapScript )
203271 if err != nil {
204- return nil , 0 , err
272+ return nil , err
205273 }
206274
207275 log .Infof ("Imported static address taproot script to lnd wallet: %v" ,
208276 addr )
209277
210- address , err := m .GetTaprootAddress (
211- clientPubKey .PubKey , serverPubKey , int64 (serverParams .Expiry ),
212- )
213- if err != nil {
214- return nil , 0 , err
215- }
216-
217- return address , int64 (serverParams .Expiry ), nil
278+ return addrParams , nil
218279}
219280
220281// GetTaprootAddress returns a taproot address for the given client and server
0 commit comments