diff --git a/accounts/keystore/keystore.go b/accounts/keystore/keystore.go index 80ccd37419f9..25c3663b5c30 100644 --- a/accounts/keystore/keystore.go +++ b/accounts/keystore/keystore.go @@ -75,10 +75,19 @@ type unlocked struct { abort chan struct{} } -// NewKeyStore creates a keystore for the given directory. -func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { +// NewUninitializedKeyStore creates a keystore for the given directory, but does not load the existing keys +func NewUninitializedKeyStore(keydir string, scryptN, scryptP int) *KeyStore { keydir, _ = filepath.Abs(keydir) ks := &KeyStore{storage: &keyStorePassphrase{keydir, scryptN, scryptP}} + // Initialize the set of unlocked keys and the account cache + ks.unlocked = make(map[common.Address]*unlocked) + ks.cache, ks.changes = newAccountCache(keydir) + return ks +} + +// NewKeyStore creates a keystore for the given directory. +func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { + ks := NewUninitializedKeyStore(keydir, scryptN, scryptP) ks.init(keydir) return ks } @@ -88,19 +97,19 @@ func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { func NewPlaintextKeyStore(keydir string) *KeyStore { keydir, _ = filepath.Abs(keydir) ks := &KeyStore{storage: &keyStorePlain{keydir}} + // Initialize the set of unlocked keys and the account cache + ks.unlocked = make(map[common.Address]*unlocked) + ks.cache, ks.changes = newAccountCache(keydir) ks.init(keydir) return ks } +// init initalizes the keystore by loading the accounts func (ks *KeyStore) init(keydir string) { // Lock the mutex since the account cache might call back with events ks.mu.Lock() defer ks.mu.Unlock() - // Initialize the set of unlocked keys and the account cache - ks.unlocked = make(map[common.Address]*unlocked) - ks.cache, ks.changes = newAccountCache(keydir) - // TODO: In order for this finalizer to work, there must be no references // to ks. addressCache doesn't keep a reference but unlocked keys do, // so the finalizer will not trigger until all timed unlocks have expired. @@ -403,13 +412,23 @@ func (ks *KeyStore) expire(addr common.Address, u *unlocked, timeout time.Durati } } -// NewAccount generates a new key and stores it into the key directory, +// CreateNewAccount generates a new key and stores it into the key directory, // encrypting it with the passphrase. -func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) { +func (ks *KeyStore) CreateNewAccount(passphrase string) (accounts.Account, error) { _, account, err := storeNewKey(ks.storage, crand.Reader, passphrase) if err != nil { return accounts.Account{}, err } + return account, nil +} + +// NewAccount generates a new key and stores it into the key directory, +// encrypting it with the passphrase, and adds it to the cache +func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) { + account, err := ks.CreateNewAccount(passphrase) + if err != nil { + return account, err + } // Add the account to the cache immediately rather // than waiting for file system notifications to pick it up. ks.cache.add(account) diff --git a/cmd/geth/accountcmd.go b/cmd/geth/accountcmd.go index 0f53c92b0a3f..9dddfc387080 100644 --- a/cmd/geth/accountcmd.go +++ b/cmd/geth/accountcmd.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" "gopkg.in/urfave/cli.v1" ) @@ -291,11 +292,11 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr // accountCreate creates a new account into the keystore defined by the CLI flags. func accountCreate(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) + cfg := createConfig(ctx) + ks, _, err := node.MakeKeystoreBackend(&cfg.Node, false) - ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - account, err := ks.NewAccount(password) + password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) + account, err := ks.CreateNewAccount(password) if err != nil { utils.Fatalf("Failed to create account: %v", err) } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 27490c40486f..b9a69600d038 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -109,7 +109,7 @@ func defaultNodeConfig() node.Config { return cfg } -func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { +func createConfig(ctx *cli.Context) gethConfig { // Load defaults. cfg := gethConfig{ Eth: eth.DefaultConfig, @@ -124,9 +124,13 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { utils.Fatalf("%v", err) } } - // Apply flags. utils.SetNodeConfig(ctx, &cfg.Node) + return cfg +} + +func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { + cfg := createConfig(ctx) stack, err := node.New(&cfg.Node) if err != nil { utils.Fatalf("Failed to create the protocol stack: %v", err) diff --git a/node/config.go b/node/config.go index be9e21b4fa78..135394863c52 100644 --- a/node/config.go +++ b/node/config.go @@ -360,7 +360,7 @@ func (c *Config) parsePersistentNodes(path string) []*discover.Node { return nodes } -func makeAccountManager(conf *Config) (*accounts.Manager, string, error) { +func MakeKeystoreBackend(conf *Config, loadKeys bool) (*keystore.KeyStore, string, error) { scryptN := keystore.StandardScryptN scryptP := keystore.StandardScryptP if conf.UseLightweightKDF { @@ -395,10 +395,21 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) { if err := os.MkdirAll(keydir, 0700); err != nil { return nil, "", err } - // Assemble the account manager and supported backends - backends := []accounts.Backend{ - keystore.NewKeyStore(keydir, scryptN, scryptP), + if !loadKeys { + return keystore.NewUninitializedKeyStore(keydir, scryptN, scryptP), ephemeral, nil } + return keystore.NewKeyStore(keydir, scryptN, scryptP), ephemeral, nil +} + +func makeAccountManager(conf *Config) (*accounts.Manager, string, error) { + + ks, ephemeral, err := MakeKeystoreBackend(conf, true) + if err != nil { + return nil, "", err + } + // Assemble the account manager and supported backends + + backends := []accounts.Backend{ks} if !conf.NoUSB { // Start a USB hub for Ledger hardware wallets if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil {