diff --git a/votingpool/example_test.go b/votingpool/example_test.go index 3697494..5ac1c64 100644 --- a/votingpool/example_test.go +++ b/votingpool/example_test.go @@ -36,8 +36,19 @@ import ( var ( pubPassphrase = []byte("pubPassphrase") privPassphrase = []byte("privPassphrase") + seed = bytes.Repeat([]byte{0x2a, 0x64, 0xdf, 0x08}, 8) + fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} ) +func createWaddrmgr(ns walletdb.Namespace, params *chaincfg.Params) (*waddrmgr.Manager, error) { + err := waddrmgr.Create(ns, seed, pubPassphrase, privPassphrase, params, + fastScrypt) + if err != nil { + return nil, err + } + return waddrmgr.Open(ns, pubPassphrase, params, nil) +} + func ExampleCreate() { // Create a new walletdb.DB. See the walletdb docs for instructions on how // to do that. @@ -56,10 +67,7 @@ func ExampleCreate() { } // Create the address manager. - seed := bytes.Repeat([]byte{0x2a, 0x64, 0xdf, 0x08}, 8) - var fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} - mgr, err := waddrmgr.Create( - mgrNamespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) + mgr, err := createWaddrmgr(mgrNamespace, &chaincfg.MainNetParams) if err != nil { fmt.Println(err) return @@ -269,10 +277,7 @@ func exampleCreateMgrAndDBNamespace() (*waddrmgr.Manager, walletdb.Namespace, fu } // Create the address manager - seed := bytes.Repeat([]byte{0x2a, 0x64, 0xdf, 0x08}, 8) - var fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} - mgr, err := waddrmgr.Create( - mgrNamespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) + mgr, err := createWaddrmgr(mgrNamespace, &chaincfg.MainNetParams) if err != nil { dbTearDown() return nil, nil, nil, err @@ -331,7 +336,11 @@ func exampleCreateTxStore() (*wtxmgr.Store, func(), error) { if err != nil { return nil, nil, err } - s, err := wtxmgr.Create(wtxmgrNamespace) + err = wtxmgr.Create(wtxmgrNamespace) + if err != nil { + return nil, nil, err + } + s, err := wtxmgr.Open(wtxmgrNamespace) if err != nil { return nil, nil, err } diff --git a/votingpool/factory_test.go b/votingpool/factory_test.go index e1e4c40..751fc4c 100644 --- a/votingpool/factory_test.go +++ b/votingpool/factory_test.go @@ -149,10 +149,14 @@ func TstCreateTxStore(t *testing.T) (store *wtxmgr.Store, tearDown func()) { if err != nil { t.Fatalf("Failed to create walletdb namespace: %v", err) } - s, err := wtxmgr.Create(wtxmgrNamespace) + err = wtxmgr.Create(wtxmgrNamespace) if err != nil { t.Fatalf("Failed to create txstore: %v", err) } + s, err := wtxmgr.Open(wtxmgrNamespace) + if err != nil { + t.Fatalf("Failed to open txstore: %v", err) + } return s, func() { os.RemoveAll(dir) } } @@ -345,8 +349,12 @@ func TstCreatePool(t *testing.T) (tearDownFunc func(), mgr *waddrmgr.Manager, po t.Fatalf("Failed to create addr manager DB namespace: %v", err) } var fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} - mgr, err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, privPassphrase, + err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) + if err == nil { + mgr, err = waddrmgr.Open(mgrNamespace, pubPassphrase, + &chaincfg.MainNetParams, nil) + } if err != nil { t.Fatalf("Failed to create addr manager: %v", err) } diff --git a/waddrmgr/common_test.go b/waddrmgr/common_test.go index 261e498..be6f08b 100644 --- a/waddrmgr/common_test.go +++ b/waddrmgr/common_test.go @@ -234,8 +234,12 @@ func setupManager(t *testing.T) (tearDownFunc func(), mgr *waddrmgr.Manager) { _ = os.RemoveAll(dirName) t.Fatalf("createDbNamespace: unexpected error: %v", err) } - mgr, err = waddrmgr.Create(namespace, seed, pubPassphrase, + err = waddrmgr.Create(namespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) + if err == nil { + mgr, err = waddrmgr.Open(namespace, pubPassphrase, + &chaincfg.MainNetParams, nil) + } if err != nil { db.Close() _ = os.RemoveAll(dirName) diff --git a/waddrmgr/manager.go b/waddrmgr/manager.go index dee041f..2fb3077 100644 --- a/waddrmgr/manager.go +++ b/waddrmgr/manager.go @@ -2272,11 +2272,11 @@ func Open(namespace walletdb.Namespace, pubPassphrase []byte, chainParams *chain return loadManager(namespace, pubPassphrase, chainParams) } -// Create returns a new locked address manager in the given namespace. The -// seed must conform to the standards described in hdkeychain.NewMaster and will -// be used to create the master root node from which all hierarchical -// deterministic addresses are derived. This allows all chained addresses in -// the address manager to be recovered by using the same seed. +// Create creates a new address manager in the given namespace. The seed must +// conform to the standards described in hdkeychain.NewMaster and will be used +// to create the master root node from which all hierarchical deterministic +// addresses are derived. This allows all chained addresses in the address +// manager to be recovered by using the same seed. // // All private and public keys and information are protected by secret keys // derived from the provided private and public passphrases. The public @@ -2289,26 +2289,26 @@ func Open(namespace walletdb.Namespace, pubPassphrase []byte, chainParams *chain // // A ManagerError with an error code of ErrAlreadyExists will be returned the // address manager already exists in the specified namespace. -func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase []byte, chainParams *chaincfg.Params, config *ScryptOptions) (*Manager, error) { +func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase []byte, chainParams *chaincfg.Params, config *ScryptOptions) error { // Return an error if the manager has already been created in the given // database namespace. exists, err := managerExists(namespace) if err != nil { - return nil, err + return err } if exists { - return nil, managerError(ErrAlreadyExists, errAlreadyExists, nil) + return managerError(ErrAlreadyExists, errAlreadyExists, nil) } // Ensure the private passphrase is not empty. if len(privPassphrase) == 0 { str := "private passphrase may not be empty" - return nil, managerError(ErrEmptyPassphrase, str, nil) + return managerError(ErrEmptyPassphrase, str, nil) } // Perform the initial bucket creation and database namespace setup. if err := createManagerNS(namespace); err != nil { - return nil, err + return err } if config == nil { @@ -2322,15 +2322,16 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] root, err := hdkeychain.NewMaster(seed, chainParams) if err != nil { str := "failed to derive master extended key" - return nil, managerError(ErrKeyChain, str, err) + return managerError(ErrKeyChain, str, err) } // Derive the cointype key according to BIP0044. coinTypeKeyPriv, err := deriveCoinTypeKey(root, chainParams.HDCoinType) if err != nil { str := "failed to derive cointype extended key" - return nil, managerError(ErrKeyChain, str, err) + return managerError(ErrKeyChain, str, err) } + defer coinTypeKeyPriv.Zero() // Derive the account key for the first account according to BIP0044. acctKeyPriv, err := deriveAccountKey(coinTypeKeyPriv, 0) @@ -2339,11 +2340,11 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] // required hierarchy can't be derived due to invalid child. if err == hdkeychain.ErrInvalidChild { str := "the provided seed is unusable" - return nil, managerError(ErrKeyChain, str, + return managerError(ErrKeyChain, str, hdkeychain.ErrUnusableSeed) } - return nil, err + return err } // Ensure the branch keys can be derived for the provided seed according @@ -2353,18 +2354,18 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] // required hierarchy can't be derived due to invalid child. if err == hdkeychain.ErrInvalidChild { str := "the provided seed is unusable" - return nil, managerError(ErrKeyChain, str, + return managerError(ErrKeyChain, str, hdkeychain.ErrUnusableSeed) } - return nil, err + return err } // The address manager needs the public extended key for the account. acctKeyPub, err := acctKeyPriv.Neuter() if err != nil { str := "failed to convert private key for account 0" - return nil, managerError(ErrKeyChain, str, err) + return managerError(ErrKeyChain, str, err) } // Generate new master keys. These master keys are used to protect the @@ -2372,13 +2373,14 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] masterKeyPub, err := newSecretKey(&pubPassphrase, config) if err != nil { str := "failed to master public key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } masterKeyPriv, err := newSecretKey(&privPassphrase, config) if err != nil { str := "failed to master private key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } + defer masterKeyPriv.Zero() // Generate the private passphrase salt. This is used when hashing // passwords to detect whether an unlock can be avoided when the manager @@ -2387,7 +2389,7 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] _, err = rand.Read(privPassphraseSalt[:]) if err != nil { str := "failed to read random source for passphrase salt" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } // Generate new crypto public, private, and script keys. These keys are @@ -2396,63 +2398,65 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] cryptoKeyPub, err := newCryptoKey() if err != nil { str := "failed to generate crypto public key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } cryptoKeyPriv, err := newCryptoKey() if err != nil { str := "failed to generate crypto private key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } + defer cryptoKeyPriv.Zero() cryptoKeyScript, err := newCryptoKey() if err != nil { str := "failed to generate crypto script key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } + defer cryptoKeyScript.Zero() // Encrypt the crypto keys with the associated master keys. cryptoKeyPubEnc, err := masterKeyPub.Encrypt(cryptoKeyPub.Bytes()) if err != nil { str := "failed to encrypt crypto public key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } cryptoKeyPrivEnc, err := masterKeyPriv.Encrypt(cryptoKeyPriv.Bytes()) if err != nil { str := "failed to encrypt crypto private key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } cryptoKeyScriptEnc, err := masterKeyPriv.Encrypt(cryptoKeyScript.Bytes()) if err != nil { str := "failed to encrypt crypto script key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } // Encrypt the cointype keys with the associated crypto keys. coinTypeKeyPub, err := coinTypeKeyPriv.Neuter() if err != nil { str := "failed to convert cointype private key" - return nil, managerError(ErrKeyChain, str, err) + return managerError(ErrKeyChain, str, err) } coinTypePubEnc, err := cryptoKeyPub.Encrypt([]byte(coinTypeKeyPub.String())) if err != nil { str := "failed to encrypt cointype public key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } coinTypePrivEnc, err := cryptoKeyPriv.Encrypt([]byte(coinTypeKeyPriv.String())) if err != nil { str := "failed to encrypt cointype private key" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } // Encrypt the default account keys with the associated crypto keys. acctPubEnc, err := cryptoKeyPub.Encrypt([]byte(acctKeyPub.String())) if err != nil { str := "failed to encrypt public key for account 0" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } acctPrivEnc, err := cryptoKeyPriv.Encrypt([]byte(acctKeyPriv.String())) if err != nil { str := "failed to encrypt private key for account 0" - return nil, managerError(ErrCrypto, str, err) + return managerError(ErrCrypto, str, err) } // Use the genesis block for the passed chain as the created at block @@ -2523,16 +2527,8 @@ func Create(namespace walletdb.Namespace, seed, pubPassphrase, privPassphrase [] return err }) if err != nil { - return nil, maybeConvertDbError(err) + return maybeConvertDbError(err) } - // The new address manager is locked by default, so clear the master, - // crypto private, crypto script and cointype keys from memory. - masterKeyPriv.Zero() - cryptoKeyPriv.Zero() - cryptoKeyScript.Zero() - coinTypeKeyPriv.Zero() - return newManager(namespace, chainParams, masterKeyPub, masterKeyPriv, - cryptoKeyPub, cryptoKeyPrivEnc, cryptoKeyScriptEnc, syncInfo, - privPassphraseSalt), nil + return nil } diff --git a/waddrmgr/manager_test.go b/waddrmgr/manager_test.go index 1d66aa3..8c76136 100644 --- a/waddrmgr/manager_test.go +++ b/waddrmgr/manager_test.go @@ -1706,19 +1706,25 @@ func TestManager(t *testing.T) { } // Create a new manager. - mgr, err := waddrmgr.Create(mgrNamespace, seed, pubPassphrase, + err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) if err != nil { t.Errorf("Create: unexpected error: %v", err) return } + mgr, err := waddrmgr.Open(mgrNamespace, pubPassphrase, + &chaincfg.MainNetParams, nil) + if err != nil { + t.Errorf("Open: unexpected error: %v", err) + return + } // NOTE: Not using deferred close here since part of the tests is // explicitly closing the manager and then opening the existing one. // Attempt to create the manager again to ensure the expected error is // returned. - _, err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, + err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, privPassphrase, &chaincfg.MainNetParams, fastScrypt) if !checkManagerError(t, "Create existing", err, waddrmgr.ErrAlreadyExists) { mgr.Close() diff --git a/wallet/loader.go b/wallet/loader.go index 20a8e9b..dc274c1 100644 --- a/wallet/loader.go +++ b/wallet/loader.go @@ -11,11 +11,9 @@ import ( "sync" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcwallet/internal/prompt" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/walletdb" - "github.com/btcsuite/btcwallet/wtxmgr" ) const ( @@ -117,46 +115,14 @@ func (l *Loader) CreateNewWallet(pubPassphrase, privPassphrase, seed []byte) (*W return nil, err } - // If a seed was provided, ensure that it is of valid length. Otherwise, - // we generate a random seed for the wallet with the recommended seed - // length. - if seed != nil { - if len(seed) < hdkeychain.MinSeedBytes || - len(seed) > hdkeychain.MaxSeedBytes { - - return nil, hdkeychain.ErrInvalidSeedLen - } - } else { - hdSeed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen) - if err != nil { - return nil, err - } - seed = hdSeed - } - - // Create the address manager. - addrMgrNamespace, err := db.Namespace(waddrmgrNamespaceKey) - if err != nil { - return nil, err - } - _, err = waddrmgr.Create(addrMgrNamespace, seed, pubPassphrase, - privPassphrase, l.chainParams, nil) - if err != nil { - return nil, err - } - - // Create empty transaction manager. - txMgrNamespace, err := db.Namespace(wtxmgrNamespaceKey) - if err != nil { - return nil, err - } - _, err = wtxmgr.Create(txMgrNamespace) + // Initialize the newly created database for the wallet before opening. + err = Create(db, pubPassphrase, privPassphrase, seed, l.chainParams) if err != nil { return nil, err } // Open the newly-created wallet. - w, err := Open(pubPassphrase, l.chainParams, db, addrMgrNamespace, txMgrNamespace, nil) + w, err := Open(db, pubPassphrase, nil, l.chainParams) if err != nil { return nil, err } @@ -197,14 +163,6 @@ func (l *Loader) OpenExistingWallet(pubPassphrase []byte, canConsolePrompt bool) return nil, err } - addrMgrNS, err := db.Namespace(waddrmgrNamespaceKey) - if err != nil { - return nil, err - } - txMgrNS, err := db.Namespace(wtxmgrNamespaceKey) - if err != nil { - return nil, err - } var cbs *waddrmgr.OpenCallbacks if canConsolePrompt { cbs = &waddrmgr.OpenCallbacks{ @@ -217,7 +175,7 @@ func (l *Loader) OpenExistingWallet(pubPassphrase []byte, canConsolePrompt bool) ObtainPrivatePass: noConsole, } } - w, err := Open(pubPassphrase, l.chainParams, db, addrMgrNS, txMgrNS, cbs) + w, err := Open(db, pubPassphrase, cbs, l.chainParams) if err != nil { return nil, err } diff --git a/wallet/wallet.go b/wallet/wallet.go index 9781dd8..2b49040 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -25,6 +25,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcrpcclient" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcwallet/chain" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet/txauthor" @@ -2058,27 +2059,77 @@ func (w *Wallet) ChainParams() *chaincfg.Params { return w.chainParams } +// Create creates an new wallet, writing it to an empty database. If the passed +// seed is non-nil, it is used. Otherwise, a secure random seed of the +// recommended length is generated. +func Create(db walletdb.DB, pubPass, privPass, seed []byte, params *chaincfg.Params) error { + // If a seed was provided, ensure that it is of valid length. Otherwise, + // we generate a random seed for the wallet with the recommended seed + // length. + if seed == nil { + hdSeed, err := hdkeychain.GenerateSeed( + hdkeychain.RecommendedSeedLen) + if err != nil { + return err + } + seed = hdSeed + } + if len(seed) < hdkeychain.MinSeedBytes || + len(seed) > hdkeychain.MaxSeedBytes { + return hdkeychain.ErrInvalidSeedLen + } + + // Create the address manager. + addrMgrNamespace, err := db.Namespace(waddrmgrNamespaceKey) + if err != nil { + return err + } + err = waddrmgr.Create(addrMgrNamespace, seed, pubPass, privPass, + params, nil) + if err != nil { + return err + } + + // Create empty transaction manager. + txMgrNamespace, err := db.Namespace(wtxmgrNamespaceKey) + if err != nil { + return err + } + return wtxmgr.Create(txMgrNamespace) +} + // Open loads an already-created wallet from the passed database and namespaces. -func Open(pubPass []byte, params *chaincfg.Params, db walletdb.DB, waddrmgrNS, wtxmgrNS walletdb.Namespace, cbs *waddrmgr.OpenCallbacks) (*Wallet, error) { - addrMgr, err := waddrmgr.Open(waddrmgrNS, pubPass, params, cbs) +func Open(db walletdb.DB, pubPass []byte, cbs *waddrmgr.OpenCallbacks, params *chaincfg.Params) (*Wallet, error) { + addrMgrNS, err := db.Namespace(waddrmgrNamespaceKey) if err != nil { return nil, err } - txMgr, err := wtxmgr.Open(wtxmgrNS) + txMgrNS, err := db.Namespace(wtxmgrNamespaceKey) if err != nil { - if wtxmgr.IsNoExists(err) { - log.Info("No recorded transaction history -- needs full rescan") - err = addrMgr.SetSyncedTo(nil) - if err != nil { - return nil, err - } - txMgr, err = wtxmgr.Create(wtxmgrNS) - if err != nil { - return nil, err - } - } else { + return nil, err + } + addrMgr, err := waddrmgr.Open(addrMgrNS, pubPass, params, cbs) + if err != nil { + return nil, err + } + noTxMgr, err := walletdb.NamespaceIsEmpty(txMgrNS) + if err != nil { + return nil, err + } + if noTxMgr { + log.Info("No recorded transaction history -- needs full rescan") + err = addrMgr.SetSyncedTo(nil) + if err != nil { return nil, err } + err = wtxmgr.Create(txMgrNS) + if err != nil { + return nil, err + } + } + txMgr, err := wtxmgr.Open(txMgrNS) + if err != nil { + return nil, err } log.Infof("Opened wallet") // TODO: log balance? last sync height? diff --git a/walletdb/interface.go b/walletdb/interface.go index c9c129b..079ba0a 100644 --- a/walletdb/interface.go +++ b/walletdb/interface.go @@ -171,6 +171,18 @@ type Namespace interface { Update(fn func(Tx) error) error } +// NamespaceIsEmpty returns whether the namespace is empty, that is, whether there +// are no key/value pairs or nested buckets. +func NamespaceIsEmpty(namespace Namespace) (bool, error) { + var empty bool + err := namespace.View(func(tx Tx) error { + k, v := tx.RootBucket().Cursor().First() + empty = k == nil && v == nil + return nil + }) + return empty, err +} + // DB represents a collection of namespaces which are persisted. All database // access is performed through transactions which are obtained through the // specific Namespace. diff --git a/walletsetup.go b/walletsetup.go index 5a38747..63f70be 100644 --- a/walletsetup.go +++ b/walletsetup.go @@ -14,7 +14,6 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcwallet/internal/legacy/keystore" "github.com/btcsuite/btcwallet/internal/prompt" "github.com/btcsuite/btcwallet/waddrmgr" @@ -23,12 +22,6 @@ import ( _ "github.com/btcsuite/btcwallet/walletdb/bdb" ) -// Namespace keys -var ( - waddrmgrNamespaceKey = []byte("waddrmgr") - wtxmgrNamespaceKey = []byte("wtxmgr") -) - // networkDir returns the directory name of a network directory to hold wallet // files. func networkDir(dataDir string, chainParams *chaincfg.Params) string { @@ -214,12 +207,6 @@ func createSimulationWallet(cfg *config) error { // Public passphrase is the default. pubPass := []byte(wallet.InsecurePubPassphrase) - // Generate a random seed. - seed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen) - if err != nil { - return err - } - netDir := networkDir(cfg.DataDir, activeNet.Params) // Create the wallet. @@ -233,20 +220,12 @@ func createSimulationWallet(cfg *config) error { } defer db.Close() - // Create the address manager. - waddrmgrNamespace, err := db.Namespace(waddrmgrNamespaceKey) + // Create the wallet. + err = wallet.Create(db, pubPass, privPass, nil, activeNet.Params) if err != nil { return err } - manager, err := waddrmgr.Create(waddrmgrNamespace, seed, []byte(pubPass), - []byte(privPass), activeNet.Params, nil) - if err != nil { - return err - } - - manager.Close() - fmt.Println("The wallet has been created successfully.") return nil } diff --git a/wtxmgr/example_test.go b/wtxmgr/example_test.go index 16743f0..328c921 100644 --- a/wtxmgr/example_test.go +++ b/wtxmgr/example_test.go @@ -155,7 +155,12 @@ func Example_basicUsage() { } // Create (or open) the transaction store in the provided namespace. - s, err := wtxmgr.Create(ns) + err = wtxmgr.Create(ns) + if err != nil { + fmt.Println(err) + return + } + s, err := wtxmgr.Open(ns) if err != nil { fmt.Println(err) return diff --git a/wtxmgr/tx.go b/wtxmgr/tx.go index 994fe5d..2ddce70 100644 --- a/wtxmgr/tx.go +++ b/wtxmgr/tx.go @@ -148,15 +148,11 @@ func Open(namespace walletdb.Namespace) (*Store, error) { return &Store{namespace, nil}, nil // TODO: set callbacks } -// Create creates and opens a new persistent transaction store in the walletdb -// namespace. Creating the store when one already exists in this namespace will -// error with ErrAlreadyExists. -func Create(namespace walletdb.Namespace) (*Store, error) { - err := createStore(namespace) - if err != nil { - return nil, err - } - return &Store{namespace, nil}, nil // TODO: set callbacks +// Create creates a new persistent transaction store in the walletdb namespace. +// Creating the store when one already exists in this namespace will error with +// ErrAlreadyExists. +func Create(namespace walletdb.Namespace) error { + return createStore(namespace) } // moveMinedTx moves a transaction record from the unmined buckets to block diff --git a/wtxmgr/tx_test.go b/wtxmgr/tx_test.go index fb9ea03..8a23351 100644 --- a/wtxmgr/tx_test.go +++ b/wtxmgr/tx_test.go @@ -75,7 +75,11 @@ func testStore() (*Store, func(), error) { if err != nil { return nil, teardown, err } - s, err := Create(ns) + err = Create(ns) + if err != nil { + return nil, teardown, err + } + s, err := Open(ns) return s, teardown, err }