From 833e4d1319336fbb66fd8f1e473c24472d65b17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 24 Jan 2017 11:49:20 +0200 Subject: accounts, cmd, eth, internal, mobile, node: split account backends --- cmd/geth/accountcmd.go | 42 +++++++++++++++++++++++++----------------- cmd/geth/accountcmd_test.go | 6 +++--- cmd/geth/main.go | 6 ++++-- cmd/gethrpctest/main.go | 8 +++++--- cmd/swarm/main.go | 22 +++++++++++++++------- cmd/utils/flags.go | 20 +++++++++++++------- 6 files changed, 65 insertions(+), 39 deletions(-) (limited to 'cmd') diff --git a/cmd/geth/accountcmd.go b/cmd/geth/accountcmd.go index 237af99eb..3a0eb13e8 100644 --- a/cmd/geth/accountcmd.go +++ b/cmd/geth/accountcmd.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/crypto" @@ -181,30 +182,30 @@ nodes. func accountList(ctx *cli.Context) error { stack := utils.MakeNode(ctx, clientIdentifier, gitCommit) for i, acct := range stack.AccountManager().Accounts() { - fmt.Printf("Account #%d: {%x} %s\n", i, acct.Address, acct.File) + fmt.Printf("Account #%d: {%x} %s\n", i, acct.Address, acct.URL) } return nil } // tries unlocking the specified account a few times. -func unlockAccount(ctx *cli.Context, accman *accounts.Manager, address string, i int, passwords []string) (accounts.Account, string) { - account, err := utils.MakeAddress(accman, address) +func unlockAccount(ctx *cli.Context, ks *keystore.KeyStore, address string, i int, passwords []string) (accounts.Account, string) { + account, err := utils.MakeAddress(ks, address) if err != nil { utils.Fatalf("Could not list accounts: %v", err) } for trials := 0; trials < 3; trials++ { prompt := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", address, trials+1, 3) password := getPassPhrase(prompt, false, i, passwords) - err = accman.Unlock(account, password) + err = ks.Unlock(account, password) if err == nil { glog.V(logger.Info).Infof("Unlocked account %x", account.Address) return account, password } - if err, ok := err.(*accounts.AmbiguousAddrError); ok { + if err, ok := err.(*keystore.AmbiguousAddrError); ok { glog.V(logger.Info).Infof("Unlocked account %x", account.Address) - return ambiguousAddrRecovery(accman, err, password), password + return ambiguousAddrRecovery(ks, err, password), password } - if err != accounts.ErrDecrypt { + if err != keystore.ErrDecrypt { // No need to prompt again if the error is not decryption-related. break } @@ -244,15 +245,15 @@ func getPassPhrase(prompt string, confirmation bool, i int, passwords []string) return password } -func ambiguousAddrRecovery(am *accounts.Manager, err *accounts.AmbiguousAddrError, auth string) accounts.Account { +func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrError, auth string) accounts.Account { fmt.Printf("Multiple key files exist for address %x:\n", err.Addr) for _, a := range err.Matches { - fmt.Println(" ", a.File) + fmt.Println(" ", a.URL) } fmt.Println("Testing your passphrase against all of them...") var match *accounts.Account for _, a := range err.Matches { - if err := am.Unlock(a, auth); err == nil { + if err := ks.Unlock(a, auth); err == nil { match = &a break } @@ -260,11 +261,11 @@ func ambiguousAddrRecovery(am *accounts.Manager, err *accounts.AmbiguousAddrErro if match == nil { utils.Fatalf("None of the listed files could be unlocked.") } - fmt.Printf("Your passphrase unlocked %s\n", match.File) + fmt.Printf("Your passphrase unlocked %s\n", match.URL) fmt.Println("In order to avoid this warning, you need to remove the following duplicate key files:") for _, a := range err.Matches { if a != *match { - fmt.Println(" ", a.File) + fmt.Println(" ", a.URL) } } return *match @@ -275,7 +276,8 @@ func accountCreate(ctx *cli.Context) error { stack := utils.MakeNode(ctx, clientIdentifier, gitCommit) 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 := stack.AccountManager().NewAccount(password) + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + account, err := ks.NewAccount(password) if err != nil { utils.Fatalf("Failed to create account: %v", err) } @@ -290,9 +292,11 @@ func accountUpdate(ctx *cli.Context) error { utils.Fatalf("No accounts specified to update") } stack := utils.MakeNode(ctx, clientIdentifier, gitCommit) - account, oldPassword := unlockAccount(ctx, stack.AccountManager(), ctx.Args().First(), 0, nil) + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + + account, oldPassword := unlockAccount(ctx, ks, ctx.Args().First(), 0, nil) newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil) - if err := stack.AccountManager().Update(account, oldPassword, newPassword); err != nil { + if err := ks.Update(account, oldPassword, newPassword); err != nil { utils.Fatalf("Could not update the account: %v", err) } return nil @@ -310,7 +314,9 @@ func importWallet(ctx *cli.Context) error { stack := utils.MakeNode(ctx, clientIdentifier, gitCommit) passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx)) - acct, err := stack.AccountManager().ImportPreSaleKey(keyJson, passphrase) + + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + acct, err := ks.ImportPreSaleKey(keyJson, passphrase) if err != nil { utils.Fatalf("%v", err) } @@ -329,7 +335,9 @@ func accountImport(ctx *cli.Context) error { } stack := utils.MakeNode(ctx, clientIdentifier, gitCommit) passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) - acct, err := stack.AccountManager().ImportECDSA(key, passphrase) + + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + acct, err := ks.ImportECDSA(key, passphrase) if err != nil { utils.Fatalf("Could not create the account: %v", err) } diff --git a/cmd/geth/accountcmd_test.go b/cmd/geth/accountcmd_test.go index 113df983e..7e03d7548 100644 --- a/cmd/geth/accountcmd_test.go +++ b/cmd/geth/accountcmd_test.go @@ -35,7 +35,7 @@ import ( func tmpDatadirWithKeystore(t *testing.T) string { datadir := tmpdir(t) keystore := filepath.Join(datadir, "keystore") - source := filepath.Join("..", "..", "accounts", "testdata", "keystore") + source := filepath.Join("..", "..", "accounts", "keystore", "testdata", "keystore") if err := cp.CopyAll(keystore, source); err != nil { t.Fatal(err) } @@ -230,7 +230,7 @@ Fatal: Failed to unlock account 0 (could not decrypt key with given passphrase) } func TestUnlockFlagAmbiguous(t *testing.T) { - store := filepath.Join("..", "..", "accounts", "testdata", "dupes") + store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") geth := runGeth(t, "--keystore", store, "--nat", "none", "--nodiscover", "--dev", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", @@ -267,7 +267,7 @@ In order to avoid this warning, you need to remove the following duplicate key f } func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) { - store := filepath.Join("..", "..", "accounts", "testdata", "dupes") + store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") geth := runGeth(t, "--keystore", store, "--nat", "none", "--nodiscover", "--dev", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a") diff --git a/cmd/geth/main.go b/cmd/geth/main.go index d7e4cc7b5..2c4963cac 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/console" @@ -245,12 +246,13 @@ func startNode(ctx *cli.Context, stack *node.Node) { utils.StartNode(stack) // Unlock any account specifically requested - accman := stack.AccountManager() + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + passwords := utils.MakePasswordList(ctx) accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") for i, account := range accounts { if trimmed := strings.TrimSpace(account); trimmed != "" { - unlockAccount(ctx, accman, trimmed, i, passwords) + unlockAccount(ctx, ks, trimmed, i, passwords) } } // Start auxiliary services if enabled diff --git a/cmd/gethrpctest/main.go b/cmd/gethrpctest/main.go index 850bf8eb2..348eeebce 100644 --- a/cmd/gethrpctest/main.go +++ b/cmd/gethrpctest/main.go @@ -23,6 +23,7 @@ import ( "os" "os/signal" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" @@ -99,17 +100,18 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) { return nil, err } // Create the keystore and inject an unlocked account if requested - accman := stack.AccountManager() + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) + if len(privkey) > 0 { key, err := crypto.HexToECDSA(privkey) if err != nil { return nil, err } - a, err := accman.ImportECDSA(key, "") + a, err := ks.ImportECDSA(key, "") if err != nil { return nil, err } - if err := accman.Unlock(a, ""); err != nil { + if err := ks.Unlock(a, ""); err != nil { return nil, err } } diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 546c646f1..466b17f30 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -26,6 +26,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/console" @@ -327,29 +328,36 @@ func getAccount(ctx *cli.Context, stack *node.Node) *ecdsa.PrivateKey { return key } // Otherwise try getting it from the keystore. - return decryptStoreAccount(stack.AccountManager(), keyid) + am := stack.AccountManager() + ks := am.Backend(keystore.BackendType).(*keystore.KeyStore) + + return decryptStoreAccount(ks, keyid) } -func decryptStoreAccount(accman *accounts.Manager, account string) *ecdsa.PrivateKey { +func decryptStoreAccount(ks *keystore.KeyStore, account string) *ecdsa.PrivateKey { var a accounts.Account var err error if common.IsHexAddress(account) { - a, err = accman.Find(accounts.Account{Address: common.HexToAddress(account)}) - } else if ix, ixerr := strconv.Atoi(account); ixerr == nil { - a, err = accman.AccountByIndex(ix) + a, err = ks.Find(accounts.Account{Address: common.HexToAddress(account)}) + } else if ix, ixerr := strconv.Atoi(account); ixerr == nil && ix > 0 { + if accounts := ks.Accounts(); len(accounts) > ix { + a = accounts[ix] + } else { + err = fmt.Errorf("index %d higher than number of accounts %d", ix, len(accounts)) + } } else { utils.Fatalf("Can't find swarm account key %s", account) } if err != nil { utils.Fatalf("Can't find swarm account key: %v", err) } - keyjson, err := ioutil.ReadFile(a.File) + keyjson, err := ioutil.ReadFile(a.URL) if err != nil { utils.Fatalf("Can't load swarm account key: %v", err) } for i := 1; i <= 3; i++ { passphrase := promptPassphrase(fmt.Sprintf("Unlocking swarm account %s [%d/3]", a.Address.Hex(), i)) - key, err := accounts.DecryptKey(keyjson, passphrase) + key, err := keystore.DecryptKey(keyjson, passphrase) if err == nil { return key.PrivateKey } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 9ba33df80..1196a64b5 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/ethash" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -587,23 +588,27 @@ func MakeDatabaseHandles() int { // MakeAddress converts an account specified directly as a hex encoded string or // a key index in the key store to an internal account representation. -func MakeAddress(accman *accounts.Manager, account string) (accounts.Account, error) { +func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { // If the specified account is a valid address, return it if common.IsHexAddress(account) { return accounts.Account{Address: common.HexToAddress(account)}, nil } // Otherwise try to interpret the account as a keystore index index, err := strconv.Atoi(account) - if err != nil { + if err != nil || index < 0 { return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) } - return accman.AccountByIndex(index) + accs := ks.Accounts() + if len(accs) <= index { + return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) + } + return accs[index], nil } // MakeEtherbase retrieves the etherbase either from the directly specified // command line flags or from the keystore if CLI indexed. -func MakeEtherbase(accman *accounts.Manager, ctx *cli.Context) common.Address { - accounts := accman.Accounts() +func MakeEtherbase(ks *keystore.KeyStore, ctx *cli.Context) common.Address { + accounts := ks.Accounts() if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 { glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default") return common.Address{} @@ -613,7 +618,7 @@ func MakeEtherbase(accman *accounts.Manager, ctx *cli.Context) common.Address { return common.Address{} } // If the specified etherbase is a valid address, return it - account, err := MakeAddress(accman, etherbase) + account, err := MakeAddress(ks, etherbase) if err != nil { Fatalf("Option %q: %v", EtherbaseFlag.Name, err) } @@ -721,9 +726,10 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) { if networks > 1 { Fatalf("The %v flags are mutually exclusive", netFlags) } + ks := stack.AccountManager().Backend(keystore.BackendType).(*keystore.KeyStore) ethConf := ð.Config{ - Etherbase: MakeEtherbase(stack.AccountManager(), ctx), + Etherbase: MakeEtherbase(ks, ctx), ChainConfig: MakeChainConfig(ctx, stack), FastSync: ctx.GlobalBool(FastSyncFlag.Name), LightMode: ctx.GlobalBool(LightModeFlag.Name), -- cgit v1.2.3