Skip to content

Commit ad7cdc8

Browse files
committed
multi: use lndclient MacaroonService
Since the code for creating and using a macaroon service is the same for multiple projects (pool, loop, litd etc), the code has been unified in lndclient. So this commit removes the macaroon service code and instead uses the lndclient code.
1 parent 0d1cb3e commit ad7cdc8

File tree

6 files changed

+65
-201
lines changed

6 files changed

+65
-201
lines changed

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ require (
1010
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0
1111
github.com/jessevdk/go-flags v1.4.0
1212
github.com/lightninglabs/aperture v0.1.6-beta
13-
github.com/lightninglabs/lndclient v0.14.0-5
13+
github.com/lightninglabs/lndclient v0.14.0-8
1414
github.com/lightninglabs/loop/swapserverrpc v1.0.0
1515
github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display
1616
github.com/lightningnetwork/lnd v0.14.1-beta
1717
github.com/lightningnetwork/lnd/cert v1.1.0
1818
github.com/lightningnetwork/lnd/clock v1.1.0
19-
github.com/lightningnetwork/lnd/kvdb v1.2.1
2019
github.com/lightningnetwork/lnd/queue v1.1.0
2120
github.com/lightningnetwork/lnd/ticker v1.1.0
2221
github.com/stretchr/testify v1.7.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,8 @@ github.com/lightninglabs/aperture v0.1.6-beta/go.mod h1:9xl4mx778ZAzrB87nLHMqk+X
461461
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc=
462462
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
463463
github.com/lightninglabs/lndclient v0.11.0-4/go.mod h1:8/cTKNwgL87NX123gmlv3Xh6p1a7pvzu+40Un3PhHiI=
464-
github.com/lightninglabs/lndclient v0.14.0-5 h1:dI2/Y2fn9m5VuwMTd/DcF6y0DYdMy3pk0MPu4xNjj54=
465-
github.com/lightninglabs/lndclient v0.14.0-5/go.mod h1:2kH9vNoc29ghIkfMjxwSeK8yCxsYfR80XAJ9PU/QWWk=
464+
github.com/lightninglabs/lndclient v0.14.0-8 h1:vdwV6yFU4A7BjG2V8cpI8Kqdl2M0NSfsA+RWR+JGTko=
465+
github.com/lightninglabs/lndclient v0.14.0-8/go.mod h1:YIE/Yac69hIMiq9cm/ZC2sP4F0Llv3tC4hZGfgOhdeY=
466466
github.com/lightninglabs/neutrino v0.11.0/go.mod h1:CuhF0iuzg9Sp2HO6ZgXgayviFTn1QHdSTJlMncK80wg=
467467
github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200/go.mod h1:MlZmoKa7CJP3eR1s5yB7Rm5aSyadpKkxqAwLQmog7N0=
468468
github.com/lightninglabs/neutrino v0.12.1/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E=

loopd/daemon.go

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515
proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
1616
"github.com/lightninglabs/lndclient"
1717
"github.com/lightninglabs/loop"
18+
"github.com/lightninglabs/loop/loopdb"
1819
"github.com/lightninglabs/loop/looprpc"
19-
"github.com/lightningnetwork/lnd/kvdb"
2020
"github.com/lightningnetwork/lnd/lntypes"
2121
"github.com/lightningnetwork/lnd/macaroons"
2222
"google.golang.org/grpc"
@@ -85,8 +85,7 @@ type Daemon struct {
8585
restListener net.Listener
8686
restCtxCancel func()
8787

88-
macaroonService *macaroons.Service
89-
macaroonDB kvdb.Backend
88+
macaroonService *lndclient.MacaroonService
9089
}
9190

9291
// New creates a new instance of the loop client daemon.
@@ -200,6 +199,10 @@ func (d *Daemon) StartAsSubserver(lndGrpc *lndclient.GrpcLndServices,
200199
func (d *Daemon) ValidateMacaroon(ctx context.Context,
201200
requiredPermissions []bakery.Op, fullMethod string) error {
202201

202+
if d.macaroonService == nil {
203+
return fmt.Errorf("macaroon service has not been initialised")
204+
}
205+
203206
// Delegate the call to loop's own macaroon validator service.
204207
return d.macaroonService.ValidateMacaroon(
205208
ctx, requiredPermissions, fullMethod,
@@ -213,11 +216,14 @@ func (d *Daemon) startWebServers() error {
213216
// With our client created, let's now finish setting up and start our
214217
// RPC server. First we add the security interceptor to our gRPC server
215218
// options that checks the macaroons for validity.
216-
serverOpts, err := d.macaroonInterceptor()
219+
unaryInterceptor, streamInterceptor, err := d.macaroonService.Interceptors()
217220
if err != nil {
218221
return fmt.Errorf("error with macaroon interceptor: %v", err)
219222
}
220-
d.grpcServer = grpc.NewServer(serverOpts...)
223+
d.grpcServer = grpc.NewServer(
224+
grpc.UnaryInterceptor(unaryInterceptor),
225+
grpc.StreamInterceptor(streamInterceptor),
226+
)
221227
looprpc.RegisterSwapClientServer(d.grpcServer, d)
222228

223229
// Register our debug server if it is compiled in.
@@ -370,15 +376,43 @@ func (d *Daemon) initialize(createDefaultMacaroonFile bool) error {
370376
// stop on main context cancel. So we create it early and pass it down.
371377
d.mainCtx, d.mainCtxCancel = context.WithCancel(context.Background())
372378

373-
// Start the macaroon service and let it create its default macaroon in
374-
// case it doesn't exist yet.
375-
err = d.startMacaroonService(createDefaultMacaroonFile)
376-
if err != nil {
377-
// The client is the only thing we started yet, so if we clean
378-
// up its connection now, nothing else needs to be shut down at
379-
// this point.
380-
clientCleanup()
381-
return err
379+
// Add our debug permissions to our main set of required permissions
380+
// if compiled in.
381+
for endpoint, perm := range debugRequiredPermissions {
382+
RequiredPermissions[endpoint] = perm
383+
}
384+
385+
if createDefaultMacaroonFile {
386+
// Start the macaroon service and let it create its default
387+
// macaroon in case it doesn't exist yet.
388+
d.macaroonService, err = lndclient.NewMacaroonService(
389+
&lndclient.MacaroonServiceConfig{
390+
DBPath: d.cfg.DataDir,
391+
DBFileName: "macaroons.db",
392+
DBTimeout: loopdb.DefaultLoopDBTimeout,
393+
MacaroonLocation: loopMacaroonLocation,
394+
MacaroonPath: d.cfg.MacaroonPath,
395+
Checkers: []macaroons.Checker{
396+
macaroons.IPLockChecker,
397+
},
398+
RequiredPerms: RequiredPermissions,
399+
DBPassword: macDbDefaultPw,
400+
LndClient: &d.lnd.LndServices,
401+
EphemeralKey: lndclient.SharedKeyNUMS,
402+
KeyLocator: lndclient.SharedKeyLocator,
403+
},
404+
)
405+
if err != nil {
406+
return err
407+
}
408+
409+
if err = d.macaroonService.Start(); err != nil {
410+
// The client is the only thing we started yet, so if we
411+
// clean up its connection now, nothing else needs to be
412+
// shut down at this point.
413+
clientCleanup()
414+
return err
415+
}
382416
}
383417

384418
// Now finally fully initialize the swap client RPC server instance.
@@ -396,10 +430,15 @@ func (d *Daemon) initialize(createDefaultMacaroonFile bool) error {
396430
// Retrieve all currently existing swaps from the database.
397431
swapsList, err := d.impl.FetchSwaps()
398432
if err != nil {
433+
if d.macaroonService == nil {
434+
clientCleanup()
435+
return err
436+
}
437+
399438
// The client and the macaroon service are the only things we
400439
// started yet, so if we clean that up now, nothing else needs
401440
// to be shut down at this point.
402-
if err := d.StopMacaroonService(); err != nil {
441+
if err := d.macaroonService.Stop(); err != nil {
403442
log.Errorf("Error shutting down macaroon service: %v",
404443
err)
405444
}
@@ -520,9 +559,11 @@ func (d *Daemon) stop() {
520559
d.restCtxCancel()
521560
}
522561

523-
err := d.StopMacaroonService()
524-
if err != nil {
525-
log.Errorf("Error stopping macaroon service: %v", err)
562+
if d.macaroonService != nil {
563+
err := d.macaroonService.Stop()
564+
if err != nil {
565+
log.Errorf("Error stopping macaroon service: %v", err)
566+
}
526567
}
527568

528569
// Next, shut down the connections to lnd and the swap server.

loopd/macaroons.go

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
package loopd
22

33
import (
4-
"context"
5-
"fmt"
6-
"io/ioutil"
7-
"os"
8-
9-
"github.com/coreos/bbolt"
10-
"github.com/lightninglabs/loop/loopdb"
11-
"github.com/lightningnetwork/lnd/kvdb"
12-
"github.com/lightningnetwork/lnd/lnrpc"
13-
"github.com/lightningnetwork/lnd/macaroons"
14-
"github.com/lightningnetwork/lnd/rpcperms"
15-
"google.golang.org/grpc"
164
"gopkg.in/macaroon-bakery.v2/bakery"
175
)
186

@@ -105,36 +93,6 @@ var (
10593
}},
10694
}
10795

108-
// allPermissions is the list of all existing permissions that exist
109-
// for loopd's RPC. The default macaroon that is created on startup
110-
// contains all these permissions and is therefore equivalent to lnd's
111-
// admin.macaroon but for loop.
112-
allPermissions = []bakery.Op{{
113-
Entity: "loop",
114-
Action: "out",
115-
}, {
116-
Entity: "loop",
117-
Action: "in",
118-
}, {
119-
Entity: "swap",
120-
Action: "execute",
121-
}, {
122-
Entity: "swap",
123-
Action: "read",
124-
}, {
125-
Entity: "terms",
126-
Action: "read",
127-
}, {
128-
Entity: "auth",
129-
Action: "read",
130-
}, {
131-
Entity: "suggestions",
132-
Action: "read",
133-
}, {
134-
Entity: "suggestions",
135-
Action: "write",
136-
}}
137-
13896
// macDbDefaultPw is the default encryption password used to encrypt the
13997
// loop macaroon database. The macaroon service requires us to set a
14098
// non-nil password so we set it to an empty string. This will cause the
@@ -146,129 +104,3 @@ var (
146104
// though.
147105
macDbDefaultPw = []byte("")
148106
)
149-
150-
// startMacaroonService starts the macaroon validation service, creates or
151-
// unlocks the macaroon database and creates the default macaroon if it doesn't
152-
// exist yet. If macaroons are disabled in general in the configuration, none of
153-
// these actions are taken.
154-
func (d *Daemon) startMacaroonService(createDefaultMacaroonFile bool) error {
155-
var err error
156-
d.macaroonDB, err = kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
157-
DBPath: d.cfg.DataDir,
158-
DBFileName: "macaroons.db",
159-
DBTimeout: loopdb.DefaultLoopDBTimeout,
160-
})
161-
if err != nil {
162-
return fmt.Errorf("unable to load macaroon db: %v", err)
163-
}
164-
if err == bbolt.ErrTimeout {
165-
return fmt.Errorf("%w: couldn't obtain exclusive lock on "+
166-
"%s/%s, timed out after %v", bbolt.ErrTimeout,
167-
d.cfg.DataDir, "macaroons.db",
168-
loopdb.DefaultLoopDBTimeout)
169-
}
170-
171-
// Create the macaroon authentication/authorization service.
172-
d.macaroonService, err = macaroons.NewService(
173-
d.macaroonDB, loopMacaroonLocation, false,
174-
macaroons.IPLockChecker,
175-
)
176-
if err != nil {
177-
return fmt.Errorf("unable to set up macaroon authentication: "+
178-
"%v", err)
179-
}
180-
181-
// Try to unlock the macaroon store with the private password.
182-
err = d.macaroonService.CreateUnlock(&macDbDefaultPw)
183-
if err != nil {
184-
return fmt.Errorf("unable to unlock macaroon DB: %v", err)
185-
}
186-
187-
// There are situations in which we don't want a macaroon to be created
188-
// on disk (for example when running inside LiT stateless integrated
189-
// mode). For any other cases, we create macaroon files for the loop CLI
190-
// in the default directory.
191-
if createDefaultMacaroonFile && !lnrpc.FileExists(d.cfg.MacaroonPath) {
192-
// We don't offer the ability to rotate macaroon root keys yet,
193-
// so just use the default one since the service expects some
194-
// value to be set.
195-
idCtx := macaroons.ContextWithRootKeyID(
196-
context.Background(), macaroons.DefaultRootKeyID,
197-
)
198-
199-
// We only generate one default macaroon that contains all
200-
// existing permissions (equivalent to the admin.macaroon in
201-
// lnd). Custom macaroons can be created through the bakery
202-
// RPC. Add our debug permissions if required.
203-
allPermissions = append(allPermissions, debugPermissions...)
204-
loopMac, err := d.macaroonService.Oven.NewMacaroon(
205-
idCtx, bakery.LatestVersion, nil, allPermissions...,
206-
)
207-
if err != nil {
208-
return err
209-
}
210-
loopMacBytes, err := loopMac.M().MarshalBinary()
211-
if err != nil {
212-
return err
213-
}
214-
err = ioutil.WriteFile(d.cfg.MacaroonPath, loopMacBytes, 0644)
215-
if err != nil {
216-
if err := os.Remove(d.cfg.MacaroonPath); err != nil {
217-
log.Errorf("Unable to remove %s: %v",
218-
d.cfg.MacaroonPath, err)
219-
}
220-
return err
221-
}
222-
}
223-
224-
return nil
225-
}
226-
227-
// StopMacaroonService closes the macaroon database.
228-
func (d *Daemon) StopMacaroonService() error {
229-
var shutdownErr error
230-
if err := d.macaroonService.Close(); err != nil {
231-
log.Errorf("Error closing macaroon service: %v", err)
232-
shutdownErr = err
233-
}
234-
235-
if err := d.macaroonDB.Close(); err != nil {
236-
log.Errorf("Error closing macaroon DB: %v", err)
237-
shutdownErr = err
238-
}
239-
240-
return shutdownErr
241-
}
242-
243-
// macaroonInterceptor creates gRPC server options with the macaroon security
244-
// interceptors.
245-
func (d *Daemon) macaroonInterceptor() ([]grpc.ServerOption, error) {
246-
// Add our debug permissions to our main set of required permissions
247-
// if compiled in.
248-
for endpoint, perm := range debugRequiredPermissions {
249-
RequiredPermissions[endpoint] = perm
250-
}
251-
252-
interceptor := rpcperms.NewInterceptorChain(log, false, nil)
253-
err := interceptor.Start()
254-
if err != nil {
255-
return nil, err
256-
}
257-
258-
interceptor.SetWalletUnlocked()
259-
interceptor.AddMacaroonService(d.macaroonService)
260-
261-
for method, permissions := range RequiredPermissions {
262-
err := interceptor.AddPermission(method, permissions)
263-
if err != nil {
264-
return nil, err
265-
}
266-
}
267-
268-
unaryInterceptor := interceptor.MacaroonUnaryServerInterceptor()
269-
streamInterceptor := interceptor.MacaroonStreamServerInterceptor()
270-
return []grpc.ServerOption{
271-
grpc.UnaryInterceptor(unaryInterceptor),
272-
grpc.StreamInterceptor(streamInterceptor),
273-
}, nil
274-
}

loopd/register_default.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
//go:build !dev
12
// +build !dev
23

34
package loopd
45

56
import "gopkg.in/macaroon-bakery.v2/bakery"
67

7-
var (
8-
debugRequiredPermissions = map[string][]bakery.Op{}
9-
debugPermissions []bakery.Op
10-
)
8+
var debugRequiredPermissions = map[string][]bakery.Op{}
119

1210
// registerDebugServer is our default debug server registration function, which
1311
// excludes debug functionality.

loopd/swapclient_server_debug.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//go:build dev
12
// +build dev
23

34
package loopd
@@ -19,13 +20,6 @@ var (
1920
Action: "write",
2021
}},
2122
}
22-
23-
debugPermissions = []bakery.Op{
24-
{
25-
Entity: "debug",
26-
Action: "write",
27-
},
28-
}
2923
)
3024

3125
// registerDebugServer registers the debug server.

0 commit comments

Comments
 (0)