@@ -54,19 +54,70 @@ 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+ addr * btcutil.AddressTaproot
71+ expiry int64
72+ err error
5773}
5874
5975// NewManager creates a new address manager.
6076func NewManager (cfg * ManagerConfig , currentHeight int32 ) * Manager {
6177 m := & Manager {
62- cfg : cfg ,
78+ cfg : cfg ,
79+ addrRequest : make (chan request ),
6380 }
6481 m .currentHeight .Store (currentHeight )
6582
6683 return m
6784}
6885
69- // Run runs the address manager.
86+ // addrWorker is a worker that handles address creation requests. It calls
87+ // m.newAddress which blocks on server I/O and returns the address and expiry.
88+ func (m * Manager ) addrWorker (ctx context.Context ) {
89+ for {
90+ select {
91+ case req := <- m .addrRequest :
92+ m .handleAddrRequest (ctx , req )
93+
94+ case <- ctx .Done ():
95+ return
96+ }
97+ }
98+ }
99+
100+ // handleAddrRequest is responsible for processing a single address request.
101+ func (m * Manager ) handleAddrRequest (managerCtx context.Context , req request ) {
102+ addr , expiry , err := m .newAddress (req .ctx )
103+
104+ resp := response {
105+ addr : addr ,
106+ expiry : expiry ,
107+ err : err ,
108+ }
109+
110+ select {
111+ case req .respChan <- resp :
112+
113+ case <- req .ctx .Done ():
114+
115+ case <- managerCtx .Done ():
116+ }
117+ }
118+
119+ // Run runs the address manager. It keeps track of the current block height and
120+ // creates new static addresses as needed.
70121func (m * Manager ) Run (ctx context.Context , initChan chan struct {}) error {
71122 newBlockChan , newBlockErrChan , err :=
72123 m .cfg .ChainNotifier .RegisterBlockEpochNtfn (ctx )
@@ -75,6 +126,10 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
75126 return err
76127 }
77128
129+ // The address worker offloads the address creation with the server to a
130+ // separate go routine.
131+ go m .addrWorker (ctx )
132+
78133 // Communicate to the caller that the address manager has completed its
79134 // initialization.
80135 close (initChan )
@@ -95,10 +150,40 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
95150}
96151
97152// NewAddress creates a new static address with the server or returns an
98- // existing one.
153+ // existing one. It now sends a request to the manager's Run loop which
154+ // executes the actual address creation logic.
99155func (m * Manager ) NewAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
100156 int64 , error ) {
101157
158+ respChan := make (chan response , 1 )
159+ req := request {
160+ ctx : ctx ,
161+ respChan : respChan ,
162+ }
163+
164+ // Send the new address request to the manager run loop.
165+ select {
166+ case m .addrRequest <- req :
167+
168+ case <- ctx .Done ():
169+ return nil , 0 , ctx .Err ()
170+ }
171+
172+ // Wait for the response from the manager run loop.
173+ select {
174+ case resp := <- respChan :
175+ return resp .addr , resp .expiry , resp .err
176+
177+ case <- ctx .Done ():
178+ return nil , 0 , ctx .Err ()
179+ }
180+ }
181+
182+ // newAddress contains the body of the former NewAddress method and performs the
183+ // actual address creation/lookup according to the requested type.
184+ func (m * Manager ) newAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
185+ int64 , error ) {
186+
102187 // If there's already a static address in the database, we can return
103188 // it.
104189 m .Lock ()
0 commit comments