Expose address in keyinfo, add get command

This commit is contained in:
Ethan Frey 2017-02-28 20:07:44 +01:00
parent d5931c9ee3
commit c59e2d7d13
11 changed files with 89 additions and 17 deletions

View File

@ -10,6 +10,7 @@ the commands, and give feedback and changes.
``` ```
# keys help # keys help
Keys allows you to manage your local keystore for tendermint. Keys allows you to manage your local keystore for tendermint.
These keys may be in any format supported by go-crypto and can be These keys may be in any format supported by go-crypto and can be
@ -20,6 +21,7 @@ Usage:
keys [command] keys [command]
Available Commands: Available Commands:
get Get details of one key
list List all keys list List all keys
new Create a new public/private key pair new Create a new public/private key pair
serve Run the key manager as an http server serve Run the key manager as an http server
@ -30,7 +32,8 @@ Flags:
-o, --output string Output format (text|json) (default "text") -o, --output string Output format (text|json) (default "text")
-r, --root string root directory for config and data (default "/Users/ethan/.tlc") -r, --root string root directory for config and data (default "/Users/ethan/.tlc")
Use "keys [command] --help" for more information about a command.``` Use "keys [command] --help" for more information about a command.
```
## Getting the config file ## Getting the config file
@ -42,6 +45,8 @@ The first step is to load in root, by checking the following in order:
Once the `rootDir` is established, the script looks for a config file named `keys.{json,toml,yaml,hcl}` in that directory and parses it. These values will provide defaults for flags of the same name. Once the `rootDir` is established, the script looks for a config file named `keys.{json,toml,yaml,hcl}` in that directory and parses it. These values will provide defaults for flags of the same name.
There is an example config file for testing out locally, which writes keys to `./.mykeys`. You can
## Getting/Setting variables ## Getting/Setting variables
When we want to get the value of a user-defined variable (eg. `output`), we can call `viper.GetString("output")`, which will do the following checks, until it finds a match: When we want to get the value of a user-defined variable (eg. `output`), we can call `viper.GetString("output")`, which will do the following checks, until it finds a match:

47
cmd/get.go Normal file
View File

@ -0,0 +1,47 @@
// Copyright © 2017 Ethan Frey
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// getCmd represents the get command
var getCmd = &cobra.Command{
Use: "get <name>",
Short: "Get details of one key",
Long: `Return public details of one local key.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 || len(args[0]) == 0 {
fmt.Println("You must provide a name for the key")
return
}
name := args[0]
info, err := manager.Get(name)
if err != nil {
fmt.Println(err.Error())
return
}
printInfo(info)
},
}
func init() {
RootCmd.AddCommand(getCmd)
}

View File

@ -84,7 +84,8 @@ func bindFlags(cmd *cobra.Command, args []string) error {
// If a config file is found, read it in. // If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil { if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed()) // stderr, so if we redirect output to json file, this doesn't appear
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
} }
return validateFlags(cmd) return validateFlags(cmd)

View File

@ -22,7 +22,7 @@ import (
// updateCmd represents the update command // updateCmd represents the update command
var updateCmd = &cobra.Command{ var updateCmd = &cobra.Command{
Use: "update", Use: "update <name>",
Short: "Change the password for a private key", Short: "Change the password for a private key",
Long: `Change the password for a private key.`, Long: `Change the password for a private key.`,
Run: updatePassword, Run: updatePassword,

View File

@ -41,11 +41,15 @@ func getCheckPassword(prompt, prompt2 string) (string, error) {
func printInfo(info keys.Info) { func printInfo(info keys.Info) {
switch output { switch output {
case "text": case "text":
key, err := data.ToText(info.PubKey) addr, err := data.ToText(info.Address)
if err != nil { if err != nil {
panic(err) // really shouldn't happen... panic(err) // really shouldn't happen...
} }
fmt.Printf("%s\t%s\n", info.Name, key) sep := "\t\t"
if len(info.Name) > 7 {
sep = "\t"
}
fmt.Printf("%s%s%s\n", info.Name, sep, addr)
case "json": case "json":
json, err := data.ToJSON(info) json, err := data.ToJSON(info)
if err != nil { if err != nil {

View File

@ -40,8 +40,10 @@ func (es encryptedStorage) Delete(name string) error {
// info hardcodes the encoding of keys // info hardcodes the encoding of keys
func info(name string, key crypto.PrivKey) keys.Info { func info(name string, key crypto.PrivKey) keys.Info {
pub := key.PubKey()
return keys.Info{ return keys.Info{
Name: name, Name: name,
PubKey: crypto.PubKeyS{key.PubKey()}, Address: pub.Address(),
PubKey: crypto.PubKeyS{pub},
} }
} }

View File

@ -74,7 +74,7 @@ func (s FileStore) Get(name string) ([]byte, keys.Info, error) {
} }
key, _, err := read(priv) key, _, err := read(priv)
return key, info, err return key, info.Format(), err
} }
// List parses the key directory for public info and returns a list of // List parses the key directory for public info and returns a list of
@ -99,7 +99,7 @@ func (s FileStore) List() (keys.Infos, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
infos = append(infos, info) infos = append(infos, info.Format())
} }
} }

View File

@ -49,11 +49,13 @@ func TestBasicCRUD(t *testing.T) {
k, i, err := store.Get(name) k, i, err := store.Get(name)
require.Nil(err, "%+v", err) require.Nil(err, "%+v", err)
assert.Equal(key, k) assert.Equal(key, k)
assert.Equal(info, i) assert.Equal(info.Name, i.Name)
assert.Equal(info.PubKey, i.PubKey)
assert.NotEmpty(i.Address)
l, err = store.List() l, err = store.List()
require.Nil(err, "%+v", err) require.Nil(err, "%+v", err)
assert.Equal(1, len(l)) assert.Equal(1, len(l))
assert.Equal(info, l[0]) assert.Equal(i, l[0])
// querying a non-existent key fails // querying a non-existent key fails
_, _, err = store.Get("badname") _, _, err = store.Get("badname")

View File

@ -44,7 +44,7 @@ func (s MemStore) Get(name string) ([]byte, keys.Info, error) {
if !ok { if !ok {
err = errors.Errorf("Key named '%s' doesn't exist", name) err = errors.Errorf("Key named '%s' doesn't exist", name)
} }
return d.key, d.info, err return d.key, d.info.Format(), err
} }
// List returns the public info of all keys in the MemStore in unsorted order // List returns the public info of all keys in the MemStore in unsorted order
@ -52,7 +52,7 @@ func (s MemStore) List() (keys.Infos, error) {
res := make([]keys.Info, len(s)) res := make([]keys.Info, len(s))
i := 0 i := 0
for _, d := range s { for _, d := range s {
res[i] = d.info res[i] = d.info.Format()
i++ i++
} }
return res, nil return res, nil

View File

@ -41,11 +41,13 @@ func TestBasicCRUD(t *testing.T) {
k, i, err := store.Get(name) k, i, err := store.Get(name)
assert.Nil(err) assert.Nil(err)
assert.Equal(key, k) assert.Equal(key, k)
assert.Equal(info, i) assert.Equal(info.Name, i.Name)
assert.Equal(info.PubKey, i.PubKey)
assert.NotEmpty(i.Address)
l, err = store.List() l, err = store.List()
assert.Nil(err) assert.Nil(err)
assert.Equal(1, len(l)) assert.Equal(1, len(l))
assert.Equal(info, l[0]) assert.Equal(i, l[0])
// querying a non-existent key fails // querying a non-existent key fails
_, _, err = store.Get("badname") _, _, err = store.Get("badname")

View File

@ -4,12 +4,21 @@ import (
"sort" "sort"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
data "github.com/tendermint/go-data"
) )
// Info is the public information about a key // Info is the public information about a key
type Info struct { type Info struct {
Name string Name string `json:"name"`
PubKey crypto.PubKeyS Address data.Bytes `json:"address"`
PubKey crypto.PubKeyS `json:"pubkey"`
}
func (i *Info) Format() Info {
if !i.PubKey.Empty() {
i.Address = i.PubKey.Address()
}
return *i
} }
// Infos is a wrapper to allows alphabetical sorting of the keys // Infos is a wrapper to allows alphabetical sorting of the keys