From 81797fe29d6c56a5a151b6a2c04c3cc819169766 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 2 Oct 2019 13:14:59 -0400 Subject: [PATCH] multi: extend walletdb bolt driver with NoFreelistSync option This allows external callers to set the option instead. All tests remained with the option enabled. --- btcwallet.go | 2 +- cmd/dropwtxmgr/main.go | 2 +- waddrmgr/common_test.go | 4 ++-- waddrmgr/manager_test.go | 2 +- wallet/createtx_test.go | 2 +- wallet/loader.go | 8 +++++--- walletdb/bdb/README.md | 9 +++++---- walletdb/bdb/db.go | 4 ++-- walletdb/bdb/doc.go | 9 +++++---- walletdb/bdb/driver.go | 31 ++++++++++++++++++++----------- walletdb/bdb/driver_test.go | 2 +- walletsetup.go | 2 +- 12 files changed, 45 insertions(+), 32 deletions(-) diff --git a/btcwallet.go b/btcwallet.go index 9ffa597..3073357 100644 --- a/btcwallet.go +++ b/btcwallet.go @@ -69,7 +69,7 @@ func walletMain() error { } dbDir := networkDir(cfg.AppDataDir.Value, activeNet.Params) - loader := wallet.NewLoader(activeNet.Params, dbDir, 250) + loader := wallet.NewLoader(activeNet.Params, dbDir, true, 250) // Create and start HTTP server to serve wallet client connections. // This will be updated with the wallet and chain server RPC client diff --git a/cmd/dropwtxmgr/main.go b/cmd/dropwtxmgr/main.go index 164e6c0..8f47644 100644 --- a/cmd/dropwtxmgr/main.go +++ b/cmd/dropwtxmgr/main.go @@ -99,7 +99,7 @@ func mainInt() int { fmt.Println("Enter yes or no.") } - db, err := walletdb.Open("bdb", opts.DbPath) + db, err := walletdb.Open("bdb", opts.DbPath, true) if err != nil { fmt.Println("Failed to open database:", err) return 1 diff --git a/waddrmgr/common_test.go b/waddrmgr/common_test.go index 5edc694..1297199 100644 --- a/waddrmgr/common_test.go +++ b/waddrmgr/common_test.go @@ -242,7 +242,7 @@ func emptyDB(t *testing.T) (tearDownFunc func(), db walletdb.DB) { t.Fatalf("Failed to create db temp dir: %v", err) } dbPath := filepath.Join(dirName, "mgrtest.db") - db, err = walletdb.Create("bdb", dbPath) + db, err = walletdb.Create("bdb", dbPath, true) if err != nil { _ = os.RemoveAll(dirName) t.Fatalf("createDbNamespace: unexpected error: %v", err) @@ -263,7 +263,7 @@ func setupManager(t *testing.T) (tearDownFunc func(), db walletdb.DB, mgr *Manag t.Fatalf("Failed to create db temp dir: %v", err) } dbPath := filepath.Join(dirName, "mgrtest.db") - db, err = walletdb.Create("bdb", dbPath) + db, err = walletdb.Create("bdb", dbPath, true) if err != nil { _ = os.RemoveAll(dirName) t.Fatalf("createDbNamespace: unexpected error: %v", err) diff --git a/waddrmgr/manager_test.go b/waddrmgr/manager_test.go index 754faf3..cb80a7d 100644 --- a/waddrmgr/manager_test.go +++ b/waddrmgr/manager_test.go @@ -1651,7 +1651,7 @@ func testWatchingOnly(tc *testContext) bool { defer os.Remove(woMgrName) // Open the new database copy and get the address manager namespace. - db, err := walletdb.Open("bdb", woMgrName) + db, err := walletdb.Open("bdb", woMgrName, true) if err != nil { tc.t.Errorf("openDbNamespace: unexpected error: %v", err) return false diff --git a/wallet/createtx_test.go b/wallet/createtx_test.go index 1ffccf3..9747630 100644 --- a/wallet/createtx_test.go +++ b/wallet/createtx_test.go @@ -41,7 +41,7 @@ func TestTxToOutputsDryRun(t *testing.T) { pubPass := []byte("hello") privPass := []byte("world") - loader := NewLoader(&chaincfg.TestNet3Params, dir, 250) + loader := NewLoader(&chaincfg.TestNet3Params, dir, true, 250) w, err := loader.CreateNewWallet(pubPass, privPass, seed, time.Now()) if err != nil { t.Fatalf("unable to create wallet: %v", err) diff --git a/wallet/loader.go b/wallet/loader.go index 0d45607..5ae807e 100644 --- a/wallet/loader.go +++ b/wallet/loader.go @@ -46,6 +46,7 @@ type Loader struct { callbacks []func(*Wallet) chainParams *chaincfg.Params dbDirPath string + noFreelistSync bool recoveryWindow uint32 wallet *Wallet db walletdb.DB @@ -56,11 +57,12 @@ type Loader struct { // recovery window is non-zero, the wallet will attempt to recovery addresses // starting from the last SyncedTo height. func NewLoader(chainParams *chaincfg.Params, dbDirPath string, - recoveryWindow uint32) *Loader { + noFreelistSync bool, recoveryWindow uint32) *Loader { return &Loader{ chainParams: chainParams, dbDirPath: dbDirPath, + noFreelistSync: noFreelistSync, recoveryWindow: recoveryWindow, } } @@ -119,7 +121,7 @@ func (l *Loader) CreateNewWallet(pubPassphrase, privPassphrase, seed []byte, if err != nil { return nil, err } - db, err := walletdb.Create("bdb", dbPath) + db, err := walletdb.Create("bdb", dbPath, l.noFreelistSync) if err != nil { return nil, err } @@ -168,7 +170,7 @@ func (l *Loader) OpenExistingWallet(pubPassphrase []byte, canConsolePrompt bool) // Open the database using the boltdb backend. dbPath := filepath.Join(l.dbDirPath, walletDbName) - db, err := walletdb.Open("bdb", dbPath) + db, err := walletdb.Open("bdb", dbPath, l.noFreelistSync) if err != nil { log.Errorf("Failed to open database: %v", err) return nil, err diff --git a/walletdb/bdb/README.md b/walletdb/bdb/README.md index 5a99ae7..67ae35f 100644 --- a/walletdb/bdb/README.md +++ b/walletdb/bdb/README.md @@ -10,18 +10,19 @@ datastore. Package bdb is licensed under the copyfree ISC license. ## Usage This package is only a driver to the walletdb package and provides the database -type of "bdb". The only parameter the Open and Create functions take is the -database path as a string: +type of "bdb". The only parameters the Open and Create functions take is the +database path as a string, and an option for the database to not sync its +freelist to disk as a bool: ```Go -db, err := walletdb.Open("bdb", "path/to/database.db") +db, err := walletdb.Open("bdb", "path/to/database.db", true) if err != nil { // Handle error } ``` ```Go -db, err := walletdb.Create("bdb", "path/to/database.db") +db, err := walletdb.Create("bdb", "path/to/database.db", true) if err != nil { // Handle error } diff --git a/walletdb/bdb/db.go b/walletdb/bdb/db.go index ab611ba..046c6ac 100644 --- a/walletdb/bdb/db.go +++ b/walletdb/bdb/db.go @@ -339,7 +339,7 @@ func fileExists(name string) bool { // openDB opens the database at the provided path. walletdb.ErrDbDoesNotExist // is returned if the database doesn't exist and the create flag is not set. -func openDB(dbPath string, create bool) (walletdb.DB, error) { +func openDB(dbPath string, noFreelistSync bool, create bool) (walletdb.DB, error) { if !create && !fileExists(dbPath) { return nil, walletdb.ErrDbDoesNotExist } @@ -347,7 +347,7 @@ func openDB(dbPath string, create bool) (walletdb.DB, error) { // Specify bbolt freelist options to reduce heap pressure in case the // freelist grows to be very large. options := &bbolt.Options{ - NoFreelistSync: true, + NoFreelistSync: noFreelistSync, FreelistType: bbolt.FreelistMapType, } diff --git a/walletdb/bdb/doc.go b/walletdb/bdb/doc.go index ee25a78..6e5087a 100644 --- a/walletdb/bdb/doc.go +++ b/walletdb/bdb/doc.go @@ -9,15 +9,16 @@ datastore. Usage This package is only a driver to the walletdb package and provides the database -type of "bdb". The only parameter the Open and Create functions take is the -database path as a string: +type of "bdb". The only parameters the Open and Create functions take is the +database path as a string, and an option for the database to not sync its +freelist to disk as a bool: - db, err := walletdb.Open("bdb", "path/to/database.db") + db, err := walletdb.Open("bdb", "path/to/database.db", true) if err != nil { // Handle error } - db, err := walletdb.Create("bdb", "path/to/database.db") + db, err := walletdb.Create("bdb", "path/to/database.db", true) if err != nil { // Handle error } diff --git a/walletdb/bdb/driver.go b/walletdb/bdb/driver.go index 2a99cec..78442fd 100644 --- a/walletdb/bdb/driver.go +++ b/walletdb/bdb/driver.go @@ -15,41 +15,50 @@ const ( ) // parseArgs parses the arguments from the walletdb Open/Create methods. -func parseArgs(funcName string, args ...interface{}) (string, error) { - if len(args) != 1 { - return "", fmt.Errorf("invalid arguments to %s.%s -- "+ - "expected database path", dbType, funcName) +func parseArgs(funcName string, args ...interface{}) (string, bool, error) { + if len(args) != 2 { + return "", false, fmt.Errorf("invalid arguments to %s.%s -- "+ + "expected database path and no-freelist-sync option", + dbType, funcName) } dbPath, ok := args[0].(string) if !ok { - return "", fmt.Errorf("first argument to %s.%s is invalid -- "+ - "expected database path string", dbType, funcName) + return "", false, fmt.Errorf("first argument to %s.%s is "+ + "invalid -- expected database path string", dbType, + funcName) } - return dbPath, nil + noFreelistSync, ok := args[1].(bool) + if !ok { + return "", false, fmt.Errorf("second argument to %s.%s is "+ + "invalid -- expected no-freelist-sync bool", dbType, + funcName) + } + + return dbPath, noFreelistSync, nil } // openDBDriver is the callback provided during driver registration that opens // an existing database for use. func openDBDriver(args ...interface{}) (walletdb.DB, error) { - dbPath, err := parseArgs("Open", args...) + dbPath, noFreelistSync, err := parseArgs("Open", args...) if err != nil { return nil, err } - return openDB(dbPath, false) + return openDB(dbPath, noFreelistSync, false) } // createDBDriver is the callback provided during driver registration that // creates, initializes, and opens a database for use. func createDBDriver(args ...interface{}) (walletdb.DB, error) { - dbPath, err := parseArgs("Create", args...) + dbPath, noFreelistSync, err := parseArgs("Create", args...) if err != nil { return nil, err } - return openDB(dbPath, true) + return openDB(dbPath, noFreelistSync, true) } func init() { diff --git a/walletdb/bdb/driver_test.go b/walletdb/bdb/driver_test.go index 0b2208c..c233abe 100644 --- a/walletdb/bdb/driver_test.go +++ b/walletdb/bdb/driver_test.go @@ -130,7 +130,7 @@ func TestPersistence(t *testing.T) { // Close and reopen the database to ensure the values persist. db.Close() - db, err = walletdb.Open(dbType, dbPath) + db, err = walletdb.Open(dbType, dbPath, true) if err != nil { t.Errorf("Failed to open test database (%s) %v", dbType, err) return diff --git a/walletsetup.go b/walletsetup.go index 14412fd..951737d 100644 --- a/walletsetup.go +++ b/walletsetup.go @@ -102,7 +102,7 @@ func convertLegacyKeystore(legacyKeyStore *keystore.Store, w *wallet.Wallet) err // provided path. func createWallet(cfg *config) error { dbDir := networkDir(cfg.AppDataDir.Value, activeNet.Params) - loader := wallet.NewLoader(activeNet.Params, dbDir, 250) + loader := wallet.NewLoader(activeNet.Params, dbDir, true, 250) // When there is a legacy keystore, open it now to ensure any errors // don't end up exiting the process after the user has spent time