Exemplo n.º 1
0
// 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
}
Exemplo n.º 2
0
// 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
}
Exemplo n.º 3
0
// 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
}
Exemplo n.º 4
0
// 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
}