diff --git a/lncfg/db.go b/lncfg/db.go index a819bc930..1488ee8ce 100644 --- a/lncfg/db.go +++ b/lncfg/db.go @@ -10,7 +10,8 @@ import ( ) const ( - dbName = "channel.db" + channelDBName = "channel.db" + macaroonDBName = "macaroons.db" BoltBackend = "bolt" EtcdBackend = "etcd" @@ -19,6 +20,9 @@ const ( // NSChannelDB is the namespace name that we use for the combined graph // and channel state DB. NSChannelDB = "channeldb" + + // NSMacaroonDB is the namespace name that we use for the macaroon DB. + NSMacaroonDB = "macaroondb" ) // DB holds database configuration for LND. @@ -100,6 +104,10 @@ type DatabaseBackends struct { // contains the chain height hint related data. HeightHintDB kvdb.Backend + // MacaroonDB points to a database backend that stores the macaroon root + // keys. + MacaroonDB kvdb.Backend + // Remote indicates whether the database backends are remote, possibly // replicated instances or local bbolt backed databases. Remote bool @@ -110,14 +118,27 @@ type DatabaseBackends struct { } // GetBackends returns a set of kvdb.Backends as set in the DB config. -func (db *DB) GetBackends(ctx context.Context, dbPath string) ( - *DatabaseBackends, error) { +func (db *DB) GetBackends(ctx context.Context, chanDBPath, + walletDBPath string) (*DatabaseBackends, error) { // We keep track of all the kvdb backends we actually open and return a // reference to their close function so they can be cleaned up properly // on error or shutdown. closeFuncs := make(map[string]func() error) + // If we need to return early because of an error, we invoke any close + // function that has been initialized so far. + returnEarly := true + defer func() { + if !returnEarly { + return + } + + for _, closeFunc := range closeFuncs { + _ = closeFunc() + } + }() + if db.Backend == EtcdBackend { etcdBackend, err := kvdb.Open( kvdb.EtcdBackendName, ctx, db.Etcd, @@ -127,10 +148,12 @@ func (db *DB) GetBackends(ctx context.Context, dbPath string) ( } closeFuncs[NSChannelDB] = etcdBackend.Close + returnEarly = false return &DatabaseBackends{ GraphDB: etcdBackend, ChanStateDB: etcdBackend, HeightHintDB: etcdBackend, + MacaroonDB: etcdBackend, Remote: true, CloseFuncs: closeFuncs, }, nil @@ -138,8 +161,8 @@ func (db *DB) GetBackends(ctx context.Context, dbPath string) ( // We're using all bbolt based databases by default. boltBackend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{ - DBPath: dbPath, - DBFileName: dbName, + DBPath: chanDBPath, + DBFileName: channelDBName, DBTimeout: db.Bolt.DBTimeout, NoFreelistSync: !db.Bolt.SyncFreelist, AutoCompact: db.Bolt.AutoCompact, @@ -150,10 +173,25 @@ func (db *DB) GetBackends(ctx context.Context, dbPath string) ( } closeFuncs[NSChannelDB] = boltBackend.Close + macaroonBackend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{ + DBPath: walletDBPath, + DBFileName: macaroonDBName, + DBTimeout: db.Bolt.DBTimeout, + NoFreelistSync: !db.Bolt.SyncFreelist, + AutoCompact: db.Bolt.AutoCompact, + AutoCompactMinAge: db.Bolt.AutoCompactMinAge, + }) + if err != nil { + return nil, fmt.Errorf("error opening macaroon DB: %v", err) + } + closeFuncs[NSMacaroonDB] = macaroonBackend.Close + + returnEarly = false return &DatabaseBackends{ GraphDB: boltBackend, ChanStateDB: boltBackend, HeightHintDB: boltBackend, + MacaroonDB: macaroonBackend, CloseFuncs: closeFuncs, }, nil } diff --git a/lnd.go b/lnd.go index 390c86cda..f6977b3bd 100644 --- a/lnd.go +++ b/lnd.go @@ -480,6 +480,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error } pwService.SetLoaderOpts([]btcwallet.LoaderOption{loaderOpt}) + pwService.SetMacaroonDB(dbs.macaroonDB) walletExists, err := pwService.WalletExists() if err != nil { return err @@ -584,8 +585,8 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error if !cfg.NoMacaroons { // Create the macaroon authentication/authorization service. macaroonService, err = macaroons.NewService( - cfg.networkDir, "lnd", walletInitParams.StatelessInit, - cfg.DB.Bolt.DBTimeout, macaroons.IPLockChecker, + dbs.macaroonDB, "lnd", walletInitParams.StatelessInit, + macaroons.IPLockChecker, ) if err != nil { err := fmt.Errorf("unable to set up macaroon "+ @@ -1326,11 +1327,6 @@ type WalletUnlockParams struct { // createWalletUnlockerService creates a WalletUnlockerService from the passed // config. func createWalletUnlockerService(cfg *Config) *walletunlocker.UnlockerService { - chainConfig := cfg.Bitcoin - if cfg.registeredChains.PrimaryChain() == chainreg.LitecoinChain { - chainConfig = cfg.Litecoin - } - // The macaroonFiles are passed to the wallet unlocker so they can be // deleted and recreated in case the root macaroon key is also changed // during the change password operation. @@ -1339,8 +1335,7 @@ func createWalletUnlockerService(cfg *Config) *walletunlocker.UnlockerService { } return walletunlocker.New( - chainConfig.ChainDir, cfg.ActiveNetParams.Params, - !cfg.SyncFreelist, macaroonFiles, cfg.DB.Bolt.DBTimeout, + cfg.ActiveNetParams.Params, macaroonFiles, cfg.ResetWalletTransactions, nil, ) } @@ -1620,6 +1615,7 @@ type databaseInstances struct { graphDB *channeldb.DB chanStateDB *channeldb.DB heightHintDB kvdb.Backend + macaroonDB kvdb.Backend } // initializeDatabases extracts the current databases that we'll use for normal @@ -1639,7 +1635,9 @@ func initializeDatabases(ctx context.Context, startOpenTime := time.Now() - databaseBackends, err := cfg.DB.GetBackends(ctx, cfg.graphDatabaseDir()) + databaseBackends, err := cfg.DB.GetBackends( + ctx, cfg.graphDatabaseDir(), cfg.networkDir, + ) if err != nil { return nil, nil, fmt.Errorf("unable to obtain database "+ "backends: %v", err) @@ -1650,6 +1648,7 @@ func initializeDatabases(ctx context.Context, // within that DB. dbs := &databaseInstances{ heightHintDB: databaseBackends.HeightHintDB, + macaroonDB: databaseBackends.MacaroonDB, } cleanUp := func() { // We can just close the returned close functions directly. Even diff --git a/macaroons/service.go b/macaroons/service.go index 69d9afa70..808c238ed 100644 --- a/macaroons/service.go +++ b/macaroons/service.go @@ -4,9 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "os" - "path" - "time" "github.com/lightningnetwork/lnd/kvdb" "google.golang.org/grpc/metadata" @@ -17,10 +14,6 @@ import ( ) var ( - // DBFilename is the filename within the data directory which contains - // the macaroon stores. - DBFilename = "macaroons.db" - // ErrMissingRootKeyID specifies the root key ID is missing. ErrMissingRootKeyID = fmt.Errorf("missing root key ID") @@ -68,34 +61,17 @@ type Service struct { StatelessInit bool } -// NewService returns a service backed by the macaroon Bolt DB stored in the -// passed directory. The `checks` argument can be any of the `Checker` type -// functions defined in this package, or a custom checker if desired. This -// constructor prevents double-registration of checkers to prevent panics, so -// listing the same checker more than once is not harmful. Default checkers, -// such as those for `allow`, `time-before`, `declared`, and `error` caveats -// are registered automatically and don't need to be added. -func NewService(dir, location string, statelessInit bool, - dbTimeout time.Duration, checks ...Checker) (*Service, error) { +// NewService returns a service backed by the macaroon DB backend. The `checks` +// argument can be any of the `Checker` type functions defined in this package, +// or a custom checker if desired. This constructor prevents double-registration +// of checkers to prevent panics, so listing the same checker more than once is +// not harmful. Default checkers, such as those for `allow`, `time-before`, +// `declared`, and `error` caveats are registered automatically and don't need +// to be added. +func NewService(db kvdb.Backend, location string, statelessInit bool, + checks ...Checker) (*Service, error) { - // Ensure that the path to the directory exists. - if _, err := os.Stat(dir); os.IsNotExist(err) { - if err := os.MkdirAll(dir, 0700); err != nil { - return nil, err - } - } - - // Open the database that we'll use to store the primary macaroon key, - // and all generated macaroons+caveats. - macaroonDB, err := kvdb.Create( - kvdb.BoltBackendName, path.Join(dir, DBFilename), true, - dbTimeout, - ) - if err != nil { - return nil, err - } - - rootKeyStore, err := NewRootKeyStorage(macaroonDB) + rootKeyStore, err := NewRootKeyStorage(db) if err != nil { return nil, err } diff --git a/macaroons/service_test.go b/macaroons/service_test.go index b57a262a5..00b8c9bf6 100644 --- a/macaroons/service_test.go +++ b/macaroons/service_test.go @@ -33,7 +33,7 @@ var ( // default password of 'hello'. Only the path to the temporary // DB file is returned, because the service will open the file // and read the store on its own. -func setupTestRootKeyStorage(t *testing.T) string { +func setupTestRootKeyStorage(t *testing.T) (string, kvdb.Backend) { tempDir, err := ioutil.TempDir("", "macaroonstore-") if err != nil { t.Fatalf("Error creating temp dir: %v", err) @@ -55,21 +55,20 @@ func setupTestRootKeyStorage(t *testing.T) string { if err != nil { t.Fatalf("error creating unlock: %v", err) } - return tempDir + return tempDir, db } // TestNewService tests the creation of the macaroon service. func TestNewService(t *testing.T) { // First, initialize a dummy DB file with a store that the service // can read from. Make sure the file is removed in the end. - tempDir := setupTestRootKeyStorage(t) + tempDir, db := setupTestRootKeyStorage(t) defer os.RemoveAll(tempDir) // Second, create the new service instance, unlock it and pass in a // checker that we expect it to add to the bakery. service, err := macaroons.NewService( - tempDir, "lnd", false, kvdb.DefaultDBTimeout, - macaroons.IPLockChecker, + db, "lnd", false, macaroons.IPLockChecker, ) if err != nil { t.Fatalf("Error creating new service: %v", err) @@ -117,11 +116,10 @@ func TestNewService(t *testing.T) { // incoming context. func TestValidateMacaroon(t *testing.T) { // First, initialize the service and unlock it. - tempDir := setupTestRootKeyStorage(t) + tempDir, db := setupTestRootKeyStorage(t) defer os.RemoveAll(tempDir) service, err := macaroons.NewService( - tempDir, "lnd", false, kvdb.DefaultDBTimeout, - macaroons.IPLockChecker, + db, "lnd", false, macaroons.IPLockChecker, ) if err != nil { t.Fatalf("Error creating new service: %v", err) @@ -175,14 +173,13 @@ func TestValidateMacaroon(t *testing.T) { func TestListMacaroonIDs(t *testing.T) { // First, initialize a dummy DB file with a store that the service // can read from. Make sure the file is removed in the end. - tempDir := setupTestRootKeyStorage(t) + tempDir, db := setupTestRootKeyStorage(t) defer os.RemoveAll(tempDir) // Second, create the new service instance, unlock it and pass in a // checker that we expect it to add to the bakery. service, err := macaroons.NewService( - tempDir, "lnd", false, kvdb.DefaultDBTimeout, - macaroons.IPLockChecker, + db, "lnd", false, macaroons.IPLockChecker, ) require.NoError(t, err, "Error creating new service") defer service.Close() @@ -208,14 +205,13 @@ func TestDeleteMacaroonID(t *testing.T) { // First, initialize a dummy DB file with a store that the service // can read from. Make sure the file is removed in the end. - tempDir := setupTestRootKeyStorage(t) + tempDir, db := setupTestRootKeyStorage(t) defer os.RemoveAll(tempDir) // Second, create the new service instance, unlock it and pass in a // checker that we expect it to add to the bakery. service, err := macaroons.NewService( - tempDir, "lnd", false, kvdb.DefaultDBTimeout, - macaroons.IPLockChecker, + db, "lnd", false, macaroons.IPLockChecker, ) require.NoError(t, err, "Error creating new service") defer service.Close() diff --git a/macaroons/store.go b/macaroons/store.go index 80aa7ced1..7b0c33643 100644 --- a/macaroons/store.go +++ b/macaroons/store.go @@ -66,7 +66,6 @@ type RootKeyStorage struct { } // NewRootKeyStorage creates a RootKeyStorage instance. -// TODO(aakselrod): Add support for encryption of data with passphrase. func NewRootKeyStorage(db kvdb.Backend) (*RootKeyStorage, error) { // If the store's bucket doesn't exist, create it. err := kvdb.Update(db, func(tx kvdb.RwTx) error { @@ -78,7 +77,10 @@ func NewRootKeyStorage(db kvdb.Backend) (*RootKeyStorage, error) { } // Return the DB wrapped in a RootKeyStorage object. - return &RootKeyStorage{Backend: db, encKey: nil}, nil + return &RootKeyStorage{ + Backend: db, + encKey: nil, + }, nil } // CreateUnlock sets an encryption key if one is not already set, otherwise it @@ -97,7 +99,7 @@ func (r *RootKeyStorage) CreateUnlock(password *[]byte) error { return ErrPasswordRequired } - return kvdb.Update(r, func(tx kvdb.RwTx) error { + return kvdb.Update(r.Backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket(rootKeyBucketName) if bucket == nil { return ErrRootKeyBucketNotFound @@ -153,7 +155,7 @@ func (r *RootKeyStorage) ChangePassword(oldPw, newPw []byte) error { return ErrPasswordRequired } - return kvdb.Update(r, func(tx kvdb.RwTx) error { + return kvdb.Update(r.Backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket(rootKeyBucketName) if bucket == nil { return ErrRootKeyBucketNotFound @@ -225,7 +227,7 @@ func (r *RootKeyStorage) Get(_ context.Context, id []byte) ([]byte, error) { return nil, ErrStoreLocked } var rootKey []byte - err := kvdb.View(r, func(tx kvdb.RTx) error { + err := kvdb.View(r.Backend, func(tx kvdb.RTx) error { bucket := tx.ReadBucket(rootKeyBucketName) if bucket == nil { return ErrRootKeyBucketNotFound @@ -276,7 +278,7 @@ func (r *RootKeyStorage) RootKey(ctx context.Context) ([]byte, []byte, error) { return nil, nil, ErrKeyValueForbidden } - err = kvdb.Update(r, func(tx kvdb.RwTx) error { + err = kvdb.Update(r.Backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket(rootKeyBucketName) if bucket == nil { return ErrRootKeyBucketNotFound @@ -319,7 +321,7 @@ func (r *RootKeyStorage) GenerateNewRootKey() error { if r.encKey == nil { return ErrStoreLocked } - return kvdb.Update(r, func(tx kvdb.RwTx) error { + return kvdb.Update(r.Backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket(rootKeyBucketName) if bucket == nil { return ErrRootKeyBucketNotFound @@ -341,7 +343,13 @@ func (r *RootKeyStorage) Close() error { r.encKey.Zero() r.encKey = nil } - return r.Backend.Close() + + // Since we're not responsible for _creating_ the connection to our DB + // backend, we also shouldn't close it. This should be handled + // externally as to not interfere with remote DB connections in case we + // need to open/close the store twice as happens in the password change + // case. + return nil } // generateAndStoreNewRootKey creates a new random RootKeyLen-byte root key, @@ -377,7 +385,7 @@ func (r *RootKeyStorage) ListMacaroonIDs(_ context.Context) ([][]byte, error) { // Read all the items in the bucket and append the keys, which are the // root key IDs we want. - err := kvdb.View(r, func(tx kvdb.RTx) error { + err := kvdb.View(r.Backend, func(tx kvdb.RTx) error { // appendRootKey is a function closure that appends root key ID // to rootKeySlice. @@ -426,7 +434,7 @@ func (r *RootKeyStorage) DeleteMacaroonID( } var rootKeyIDDeleted []byte - err := kvdb.Update(r, func(tx kvdb.RwTx) error { + err := kvdb.Update(r.Backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket(rootKeyBucketName) // Check the key can be found. If not, return nil. diff --git a/macaroons/store_test.go b/macaroons/store_test.go index 517315c63..8dfe9e3a8 100644 --- a/macaroons/store_test.go +++ b/macaroons/store_test.go @@ -54,6 +54,7 @@ func openTestStore(t *testing.T, tempDir string) (func(), cleanup := func() { _ = store.Close() + _ = db.Close() } return cleanup, store @@ -108,6 +109,7 @@ func TestStore(t *testing.T) { require.Equal(t, macaroons.ErrAlreadyUnlocked, err) _ = store.Close() + _ = store.Backend.Close() // Between here and the re-opening of the store, it's possible to get // a double-close, but that's not such a big deal since the tests will @@ -206,6 +208,8 @@ func TestStoreChangePassword(t *testing.T) { // after closing. err = store.Close() require.NoError(t, err) + err = store.Backend.Close() + require.NoError(t, err) err = store.CreateUnlock(&newPw) require.Error(t, err) diff --git a/walletunlocker/service.go b/walletunlocker/service.go index f0535655f..b5d768686 100644 --- a/walletunlocker/service.go +++ b/walletunlocker/service.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/aezeed" "github.com/lightningnetwork/lnd/chanbackup" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet" @@ -124,30 +125,28 @@ type UnlockerService struct { // the WalletUnlocker service. MacResponseChan chan []byte - chainDir string - noFreelistSync bool - netParams *chaincfg.Params + netParams *chaincfg.Params // macaroonFiles is the path to the three generated macaroons with // different access permissions. These might not exist in a stateless // initialization of lnd. macaroonFiles []string - // dbTimeout specifies the timeout value to use when opening the wallet - // database. - dbTimeout time.Duration - // resetWalletTransactions indicates that the wallet state should be // reset on unlock to force a full chain rescan. resetWalletTransactions bool // LoaderOpts holds the functional options for the wallet loader. loaderOpts []btcwallet.LoaderOption + + // macaroonDB is an instance of a database backend that stores all + // macaroon root keys. This will be nil on initialization and must be + // set using the SetMacaroonDB method as soon as it's available. + macaroonDB kvdb.Backend } // New creates and returns a new UnlockerService. -func New(chainDir string, params *chaincfg.Params, noFreelistSync bool, - macaroonFiles []string, dbTimeout time.Duration, +func New(params *chaincfg.Params, macaroonFiles []string, resetWalletTransactions bool, loaderOpts []btcwallet.LoaderOption) *UnlockerService { @@ -158,11 +157,8 @@ func New(chainDir string, params *chaincfg.Params, noFreelistSync bool, // Make sure we buffer the channel is buffered so the main lnd // goroutine isn't blocking on writing to it. MacResponseChan: make(chan []byte, 1), - chainDir: chainDir, netParams: params, macaroonFiles: macaroonFiles, - dbTimeout: dbTimeout, - noFreelistSync: noFreelistSync, resetWalletTransactions: resetWalletTransactions, loaderOpts: loaderOpts, } @@ -174,6 +170,12 @@ func (u *UnlockerService) SetLoaderOpts(loaderOpts []btcwallet.LoaderOption) { u.loaderOpts = loaderOpts } +// SetMacaroonDB can be used to inject the macaroon database after the unlocker +// service has been hooked to the main RPC server. +func (u *UnlockerService) SetMacaroonDB(macaroonDB kvdb.Backend) { + u.macaroonDB = macaroonDB +} + func (u *UnlockerService) newLoader(recoveryWindow uint32) (*wallet.Loader, error) { @@ -607,9 +609,8 @@ func (u *UnlockerService) ChangePassword(ctx context.Context, // then close it again. // Attempt to open the macaroon DB, unlock it and then change // the passphrase. - netDir := btcwallet.NetworkDir(u.chainDir, u.netParams) macaroonService, err := macaroons.NewService( - netDir, "lnd", in.StatelessInit, u.dbTimeout, + u.macaroonDB, "lnd", in.StatelessInit, ) if err != nil { return nil, err diff --git a/walletunlocker/service_test.go b/walletunlocker/service_test.go index bacf1b5ba..85403fb0b 100644 --- a/walletunlocker/service_test.go +++ b/walletunlocker/service_test.go @@ -113,7 +113,7 @@ func openOrCreateTestMacStore(tempDir string, pw *[]byte, return nil, err } db, err := kvdb.Create( - kvdb.BoltBackendName, path.Join(netDir, macaroons.DBFilename), + kvdb.BoltBackendName, path.Join(netDir, "macaroons.db"), true, kvdb.DefaultDBTimeout, ) if err != nil { @@ -154,8 +154,7 @@ func TestGenSeed(t *testing.T) { }() service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, nil, false, testLoaderOpts(testDir), ) // Now that the service has been created, we'll ask it to generate a @@ -192,8 +191,7 @@ func TestGenSeedGenerateEntropy(t *testing.T) { _ = os.RemoveAll(testDir) }() service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, nil, false, testLoaderOpts(testDir), ) // Now that the service has been created, we'll ask it to generate a @@ -229,8 +227,7 @@ func TestGenSeedInvalidEntropy(t *testing.T) { _ = os.RemoveAll(testDir) }() service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, nil, false, testLoaderOpts(testDir), ) // Now that the service has been created, we'll ask it to generate a @@ -263,8 +260,7 @@ func TestInitWallet(t *testing.T) { // Create new UnlockerService. service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, nil, false, testLoaderOpts(testDir), ) // Once we have the unlocker service created, we'll now instantiate a @@ -352,8 +348,7 @@ func TestCreateWalletInvalidEntropy(t *testing.T) { // Create new UnlockerService. service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, nil, false, testLoaderOpts(testDir), ) // We'll attempt to init the wallet with an invalid cipher seed and @@ -385,8 +380,7 @@ func TestUnlockWallet(t *testing.T) { // Create new UnlockerService that'll also drop the wallet's history on // unlock. service := walletunlocker.New( - testDir, testNetParams, true, nil, kvdb.DefaultDBTimeout, - true, testLoaderOpts(testDir), + testNetParams, nil, true, testLoaderOpts(testDir), ) ctx := context.Background() @@ -477,9 +471,9 @@ func TestChangeWalletPasswordNewRootkey(t *testing.T) { // Create a new UnlockerService with our temp files. service := walletunlocker.New( - testDir, testNetParams, true, tempFiles, kvdb.DefaultDBTimeout, - false, testLoaderOpts(testDir), + testNetParams, tempFiles, false, testLoaderOpts(testDir), ) + service.SetMacaroonDB(store.Backend) ctx := context.Background() newPassword := []byte("hunter2???") @@ -588,10 +582,11 @@ func TestChangeWalletPasswordStateless(t *testing.T) { // Create a new UnlockerService with our temp files. service := walletunlocker.New( - testDir, testNetParams, true, []string{ + testNetParams, []string{ tempMacFile, nonExistingFile, - }, kvdb.DefaultDBTimeout, false, testLoaderOpts(testDir), + }, false, testLoaderOpts(testDir), ) + service.SetMacaroonDB(store.Backend) // Create a wallet we can try to unlock. We use the default password // so we can check that the unlocker service defaults to this when