@@ -54,19 +54,36 @@ type Manager struct {
5454 cfg * ManagerConfig
5555
5656 currentHeight atomic.Int32
57+
58+ // request is the internal channel over which address requests are sent
59+ // to the Run loop for serialized processing.
60+ requests chan request
61+ }
62+
63+ type request struct {
64+ ctx context.Context
65+ respChan chan response
66+ }
67+
68+ type response struct {
69+ addr * btcutil.AddressTaproot
70+ expiry int64
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+ requests : make (chan request ),
6379 }
6480 m .currentHeight .Store (currentHeight )
6581
6682 return m
6783}
6884
69- // Run runs the address manager.
85+ // Run runs the address manager. It keeps track of the current block height and
86+ // creates new static addresses as needed.
7087func (m * Manager ) Run (ctx context.Context , initChan chan struct {}) error {
7188 newBlockChan , newBlockErrChan , err :=
7289 m .cfg .ChainNotifier .RegisterBlockEpochNtfn (ctx )
@@ -87,6 +104,21 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
87104 case err = <- newBlockErrChan :
88105 return err
89106
107+ case req := <- m .requests :
108+ go func (r request ) {
109+ addr , expiry , e := m .newAddress (r .ctx )
110+ resp := response {
111+ addr : addr ,
112+ expiry : expiry ,
113+ err : e ,
114+ }
115+ select {
116+ case r .respChan <- resp :
117+
118+ case <- r .ctx .Done ():
119+ }
120+ }(req )
121+
90122 case <- ctx .Done ():
91123 // Signal subroutines that the manager is exiting.
92124 return ctx .Err ()
@@ -95,10 +127,40 @@ func (m *Manager) Run(ctx context.Context, initChan chan struct{}) error {
95127}
96128
97129// NewAddress creates a new static address with the server or returns an
98- // existing one.
130+ // existing one. It now sends a request to the manager's Run loop which
131+ // executes the actual address creation logic.
99132func (m * Manager ) NewAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
100133 int64 , error ) {
101134
135+ respChan := make (chan response , 1 )
136+ req := request {
137+ ctx : ctx ,
138+ respChan : respChan ,
139+ }
140+
141+ // Send the new address request to the manager run loop.
142+ select {
143+ case m .requests <- req :
144+
145+ case <- ctx .Done ():
146+ return nil , 0 , ctx .Err ()
147+ }
148+
149+ // Wait for the response from the manager run loop.
150+ select {
151+ case resp := <- respChan :
152+ return resp .addr , resp .expiry , resp .err
153+
154+ case <- ctx .Done ():
155+ return nil , 0 , ctx .Err ()
156+ }
157+ }
158+
159+ // newAddress contains the body of the former NewAddress method and performs the
160+ // actual address creation/lookup according to the requested type.
161+ func (m * Manager ) newAddress (ctx context.Context ) (* btcutil.AddressTaproot ,
162+ int64 , error ) {
163+
102164 // If there's already a static address in the database, we can return
103165 // it.
104166 m .Lock ()
0 commit comments