@@ -54,19 +54,56 @@ 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+ addr , expiry , err := m .newAddress (req .ctx )
93+ req .respChan <- response {
94+ addr : addr ,
95+ expiry : expiry ,
96+ err : err ,
97+ }
98+
99+ case <- ctx .Done ():
100+ return
101+ }
102+ }
103+ }
104+
105+ // Run runs the address manager. It keeps track of the current block height and
106+ // creates new static addresses as needed.
70107func (m * Manager ) Run (ctx context.Context , initChan chan struct {}) error {
71108 newBlockChan , newBlockErrChan , err :=
72109 m .cfg .ChainNotifier .RegisterBlockEpochNtfn (ctx )
@@ -75,6 +112,10 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
75112 return err
76113 }
77114
115+ // The address worker offloads the I/O heavy address creation with the
116+ // server to a separate go routine.
117+ go m .addrWorker (ctx )
118+
78119 // Communicate to the caller that the address manager has completed its
79120 // initialization.
80121 close (initChan )
@@ -95,10 +136,40 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
95136}
96137
97138// NewAddress creates a new static address with the server or returns an
98- // existing one.
139+ // existing one. It now sends a request to the manager's Run loop which
140+ // executes the actual address creation logic.
99141func (m * Manager ) NewAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
100142 int64 , error ) {
101143
144+ respChan := make (chan response , 1 )
145+ req := request {
146+ ctx : ctx ,
147+ respChan : respChan ,
148+ }
149+
150+ // Send the new address request to the manager run loop.
151+ select {
152+ case m .addrRequest <- req :
153+
154+ case <- ctx .Done ():
155+ return nil , 0 , ctx .Err ()
156+ }
157+
158+ // Wait for the response from the manager run loop.
159+ select {
160+ case resp := <- respChan :
161+ return resp .addr , resp .expiry , resp .err
162+
163+ case <- ctx .Done ():
164+ return nil , 0 , ctx .Err ()
165+ }
166+ }
167+
168+ // newAddress contains the body of the former NewAddress method and performs the
169+ // actual address creation/lookup according to the requested type.
170+ func (m * Manager ) newAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
171+ int64 , error ) {
172+
102173 // If there's already a static address in the database, we can return
103174 // it.
104175 m .Lock ()
0 commit comments