Skip to content

Commit 968bb50

Browse files
committed
staticaddr: serialize address creation with a channel
1 parent ba239a9 commit 968bb50

File tree

3 files changed

+114
-41
lines changed

3 files changed

+114
-41
lines changed

loopd/swapclient_server.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,14 +1579,21 @@ func (s *swapClientServer) NewStaticAddress(ctx context.Context,
15791579
_ *looprpc.NewStaticAddressRequest) (
15801580
*looprpc.NewStaticAddressResponse, error) {
15811581

1582-
staticAddress, expiry, err := s.staticAddressManager.NewAddress(ctx)
1582+
params, err := s.staticAddressManager.NewAddress(ctx)
1583+
if err != nil {
1584+
return nil, err
1585+
}
1586+
1587+
address, err := s.staticAddressManager.GetTaprootAddress(
1588+
params.ClientPubkey, params.ServerPubkey, int64(params.Expiry),
1589+
)
15831590
if err != nil {
15841591
return nil, err
15851592
}
15861593

15871594
return &looprpc.NewStaticAddressResponse{
1588-
Address: staticAddress.String(),
1589-
Expiry: uint32(expiry),
1595+
Address: address.String(),
1596+
Expiry: params.Expiry,
15901597
}, nil
15911598
}
15921599

staticaddr/address/manager.go

Lines changed: 96 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
6075
func 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.
70119
func (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

staticaddr/address/manager_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,19 @@ func TestManager(t *testing.T) {
108108
require.NoError(t, err)
109109

110110
// Create a new static address.
111-
taprootAddress, expiry, err := testContext.manager.NewAddress(ctxb)
111+
params, err := testContext.manager.NewAddress(ctxb)
112+
require.NoError(t, err)
113+
114+
address, err := testContext.manager.GetTaprootAddress(
115+
params.ClientPubkey, params.ServerPubkey, int64(params.Expiry),
116+
)
112117
require.NoError(t, err)
113118

114119
// The addresses have to match.
115-
require.Equal(t, expectedAddress.String(), taprootAddress.String())
120+
require.Equal(t, expectedAddress.String(), address.String())
116121

117122
// The expiry has to match.
118-
require.EqualValues(t, defaultExpiry, expiry)
123+
require.EqualValues(t, defaultExpiry, params.Expiry)
119124
}
120125

121126
// GenerateExpectedTaprootAddress generates the expected taproot address that

0 commit comments

Comments
 (0)