// openSavedAccount opens a named account from disk. If the wallet does not // exist, errNoWallet is returned as an error. func openSavedAccount(name string, cfg *config) (*Account, error) { netdir := networkDir(cfg.Net()) if err := checkCreateDir(netdir); err != nil { return nil, &walletOpenError{ Err: err.Error(), } } wlt := new(wallet.Wallet) txs := txstore.New() a := &Account{ name: name, Wallet: wlt, TxStore: txs, } wfilepath := accountFilename("wallet.bin", name, netdir) txfilepath := accountFilename("tx.bin", name, netdir) var wfile, txfile *os.File // Read wallet file. wfile, err := os.Open(wfilepath) if err != nil { if os.IsNotExist(err) { // Must create and save wallet first. return nil, errNoWallet } msg := fmt.Sprintf("cannot open wallet file: %s", err) return nil, &walletOpenError{msg} } defer wfile.Close() if _, err = wlt.ReadFrom(wfile); err != nil { msg := fmt.Sprintf("cannot read wallet: %s", err) return nil, &walletOpenError{msg} } // Read tx file. If this fails, return a errNoTxs error and let // the caller decide if a rescan is necessary. var finalErr error if txfile, err = os.Open(txfilepath); err != nil { log.Errorf("cannot open tx file: %s", err) // This is not a error we should immediately return with, // but other errors can be more important, so only return // this if none of the others are hit. finalErr = errNoTxs a.fullRescan = true } else { defer txfile.Close() if _, err = txs.ReadFrom(txfile); err != nil { log.Errorf("cannot read tx file: %s", err) a.fullRescan = true finalErr = errNoTxs } } return a, finalErr }
// openSavedAccount opens a named account from disk. If the wallet does not // exist, errNoWallet is returned as an error. func openSavedAccount(name string, cfg *config) (*Account, error) { netdir := networkDir(activeNet.Params) if err := checkCreateDir(netdir); err != nil { return nil, &walletOpenError{ Err: err.Error(), } } wlt := new(wallet.Wallet) txs := txstore.New() a := &Account{ name: name, Wallet: wlt, TxStore: txs, lockedOutpoints: map[btcwire.OutPoint]struct{}{}, } walletPath := accountFilename("wallet.bin", name, netdir) txstorePath := accountFilename("tx.bin", name, netdir) // Read wallet file. walletFi, err := os.Open(walletPath) if err != nil { if os.IsNotExist(err) { // Must create and save wallet first. return nil, errNoWallet } msg := fmt.Sprintf("cannot open wallet file: %s", err) return nil, &walletOpenError{msg} } if _, err = wlt.ReadFrom(walletFi); err != nil { if err := walletFi.Close(); err != nil { log.Warnf("Cannot close wallet file: %v", err) } msg := fmt.Sprintf("Cannot read wallet: %s", err) return nil, &walletOpenError{msg} } // Read txstore file. If this fails, write a new empty transaction // store to disk, mark the wallet as unsynced, and write the unsynced // wallet to disk. // // This file is opened read/write so it may be truncated if a new empty // transaction store must be written. txstoreFi, err := os.OpenFile(txstorePath, os.O_RDWR, 0) if err != nil { if err := walletFi.Close(); err != nil { log.Warnf("Cannot close wallet file: %v", err) } if err := writeUnsyncedWallet(a, walletPath); err != nil { return nil, err } // Create and write empty txstore, if it doesn't exist. if !fileExists(txstorePath) { log.Warn("Transaction store file missing") if txstoreFi, err = os.Create(txstorePath); err != nil { return nil, fmt.Errorf("cannot create new "+ "txstore file: %v", err) } defer func() { if err := txstoreFi.Close(); err != nil { log.Warnf("Cannot close transaction "+ "store file: %v", err) } }() } else { return nil, fmt.Errorf("transaction store file "+ "exists but cannot be opened: %v", err) } if _, err := txs.WriteTo(txstoreFi); err != nil { log.Warn(err) } return a, nil } if _, err = txs.ReadFrom(txstoreFi); err != nil { if err := walletFi.Close(); err != nil { log.Warnf("Cannot close wallet file: %v", err) } if err := writeUnsyncedWallet(a, walletPath); err != nil { return nil, err } defer func() { if err := txstoreFi.Close(); err != nil { log.Warnf("Cannot close transaction store "+ "file: %v", err) } }() log.Warnf("Cannot read transaction store: %s", err) if _, err := txstoreFi.Seek(0, os.SEEK_SET); err != nil { return nil, err } if err := txstoreFi.Truncate(0); err != nil { return nil, err } if _, err := txs.WriteTo(txstoreFi); err != nil { log.Warn("Cannot write new transaction store: %v", err) } log.Infof("Wrote empty transaction store file") return a, nil } if err := walletFi.Close(); err != nil { log.Warnf("Cannot close wallet file: %v", err) } if err := txstoreFi.Close(); err != nil { log.Warnf("Cannot close transaction store file: %v", err) } return a, nil }
// OpenSavedAccount opens a named account from disk. If the wallet does not // exist, ErrNoWallet is returned as an error. func OpenSavedAccount(name string, cfg *config) (*Account, error) { netdir := networkDir(cfg.Net()) if err := checkCreateDir(netdir); err != nil { return nil, err } wlt := new(wallet.Wallet) a := &Account{ Wallet: wlt, name: name, } wfilepath := accountFilename("wallet.bin", name, netdir) utxofilepath := accountFilename("utxo.bin", name, netdir) txfilepath := accountFilename("tx.bin", name, netdir) var wfile, utxofile, txfile *os.File // Read wallet file. wfile, err := os.Open(wfilepath) if err != nil { if os.IsNotExist(err) { // Must create and save wallet first. return nil, ErrNoWallet } msg := fmt.Sprintf("cannot open wallet file: %s", err) return nil, &WalletOpenError{msg} } defer wfile.Close() if _, err = wlt.ReadFrom(wfile); err != nil { msg := fmt.Sprintf("cannot read wallet: %s", err) return nil, &WalletOpenError{msg} } // Read tx file. If this fails, return a ErrNoTxs error and let // the caller decide if a rescan is necessary. var finalErr error if txfile, err = os.Open(txfilepath); err != nil { log.Errorf("cannot open tx file: %s", err) // This is not a error we should immediately return with, // but other errors can be more important, so only return // this if none of the others are hit. finalErr = ErrNoTxs } else { defer txfile.Close() var txs tx.TxStore if _, err = txs.ReadFrom(txfile); err != nil { log.Errorf("cannot read tx file: %s", err) finalErr = ErrNoTxs } else { a.TxStore = txs } } // Read utxo file. If this fails, return a ErrNoUtxos error so a // rescan can be done since the wallet creation block. var utxos tx.UtxoStore utxofile, err = os.Open(utxofilepath) if err != nil { log.Errorf("cannot open utxo file: %s", err) finalErr = ErrNoUtxos a.fullRescan = true } else { defer utxofile.Close() if _, err = utxos.ReadFrom(utxofile); err != nil { log.Errorf("cannot read utxo file: %s", err) finalErr = ErrNoUtxos } else { a.UtxoStore = utxos } } // Mark all active payment addresses as belonging to this account. for addr := range a.ActivePaymentAddresses() { MarkAddressForAccount(addr, name) } return a, finalErr }
// OpenAccount opens an account described by account in the data // directory specified by cfg. If the wallet does not exist, ErrNoWallet // is returned as an error. // // Wallets opened from this function are not set to track against a // btcd connection. func (store *AccountStore) OpenAccount(name string, cfg *config) error { wlt := new(wallet.Wallet) a := &Account{ Wallet: wlt, name: name, } netdir := networkDir(cfg.Net()) if err := checkCreateDir(netdir); err != nil { return err } wfilepath := accountFilename("wallet.bin", name, netdir) utxofilepath := accountFilename("utxo.bin", name, netdir) txfilepath := accountFilename("tx.bin", name, netdir) var wfile, utxofile, txfile *os.File // Read wallet file. wfile, err := os.Open(wfilepath) if err != nil { if os.IsNotExist(err) { // Must create and save wallet first. return ErrNoWallet } msg := fmt.Sprintf("cannot open wallet file: %s", err) return &WalletOpenError{msg} } defer wfile.Close() if _, err = wlt.ReadFrom(wfile); err != nil { msg := fmt.Sprintf("cannot read wallet: %s", err) return &WalletOpenError{msg} } // Read tx file. If this fails, return a ErrNoTxs error and let // the caller decide if a rescan is necessary. var finalErr error if txfile, err = os.Open(txfilepath); err != nil { log.Errorf("cannot open tx file: %s", err) // This is not a error we should immediately return with, // but other errors can be more important, so only return // this if none of the others are hit. finalErr = ErrNoTxs } else { defer txfile.Close() var txs tx.TxStore if _, err = txs.ReadFrom(txfile); err != nil { log.Errorf("cannot read tx file: %s", err) finalErr = ErrNoTxs } else { a.TxStore.s = txs } } // Read utxo file. If this fails, return a ErrNoUtxos error so a // rescan can be done since the wallet creation block. var utxos tx.UtxoStore utxofile, err = os.Open(utxofilepath) if err != nil { log.Errorf("cannot open utxo file: %s", err) finalErr = ErrNoUtxos } else { defer utxofile.Close() if _, err = utxos.ReadFrom(utxofile); err != nil { log.Errorf("cannot read utxo file: %s", err) finalErr = ErrNoUtxos } else { a.UtxoStore.s = utxos } } store.Lock() switch finalErr { case ErrNoTxs: // Do nothing special for now. This will be implemented when // the tx history file is properly written. store.accounts[name] = a case ErrNoUtxos: // Add wallet, but mark wallet as needing a full rescan since // the wallet creation block. This will take place when btcd // connects. a.fullRescan = true store.accounts[name] = a case nil: store.accounts[name] = a default: log.Warnf("cannot open wallet: %v", err) } store.Unlock() // Mark all active payment addresses as belonging to this account. for addr := range a.ActivePaymentAddresses() { MarkAddressForAccount(addr, name) } return nil }