Skip to content

Commit ec5b49a

Browse files
committed
staticaddr: serialize address creation with a channel
1 parent a1fb489 commit ec5b49a

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

staticaddr/address/manager.go

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
6075
func 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.
7087
func (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.
99132
func (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

Comments
 (0)