Drop on-disk keybase in favor of keyring (#5180)

* Switch keys commands to keyring

* Replace NewKeybase with NewKeyring

* Fix delete test

* Purge dead code

* Override COSMOS_SDK_TEST_KEYRING envvar to switch to a test keyring

* s/unningOnServer/unningUnattended/

C'ing @tnachen

* Add deprecated warning, output looks like the following:

```
$ gaiacli keys update --help
Command "update" is deprecated, it takes no effect with the new keyring
based backend and is provided only for backward compatibility with the
legacy LevelDB based backend.
Refer to your operating system's manual to learn how to change your
keyring's password.

Change the password used to protect private key

Usage:
  gaiacli keys update <name> [flags]

Flags:
  -h, --help   help for update

Global Flags:
      --chain-id string   Chain ID of tendermint node
  -e, --encoding string   Binary encoding (hex|b64|btc) (default "hex")
      --home string       directory for config and data (default "/home/alessio/.gaiacli")
  -o, --output string     Output format (text|json) (default "text")
      --trace             print out full stack trace on errors
```

* Update multisign command

* Modify server.GenerateSaveCoinKey()

* GenerateSaveCoinKey more modifications

* Update docs

* Update upgrade module
This commit is contained in:
Alessio Treglia 2019-11-14 15:17:21 +01:00 committed by Federico Kunze
parent 1285782ef6
commit d4c831e63a
34 changed files with 419 additions and 309 deletions

View File

@ -65,6 +65,8 @@ const (
var (
// functions aliases
NewCLIContextWithFrom = context.NewCLIContextWithFrom
NewCLIContextWithInput = context.NewCLIContextWithInput
NewCLIContextWithInputAndFrom = context.NewCLIContextWithInputAndFrom
NewCLIContext = context.NewCLIContext
GetFromFields = context.GetFromFields
ErrInvalidAccount = context.ErrInvalidAccount
@ -81,11 +83,8 @@ var (
NewRecoverKey = keys.NewRecoverKey
NewUpdateKeyReq = keys.NewUpdateKeyReq
NewDeleteKeyReq = keys.NewDeleteKeyReq
GetKeyInfo = keys.GetKeyInfo
GetPassphrase = keys.GetPassphrase
ReadPassphraseFromStdin = keys.ReadPassphraseFromStdin
NewKeyBaseFromHomeFlag = keys.NewKeyBaseFromHomeFlag
NewKeyBaseFromDir = keys.NewKeyBaseFromDir
NewKeyringFromDir = keys.NewKeyringFromDir
NewKeyringFromHomeFlag = keys.NewKeyringFromHomeFlag
NewInMemoryKeyBase = keys.NewInMemoryKeyBase
NewRestServer = lcd.NewRestServer
ServeCommand = lcd.ServeCommand

View File

@ -27,6 +27,7 @@ type CLIContext struct {
Client rpcclient.Client
ChainID string
Keybase cryptokeys.Keybase
Input io.Reader
Output io.Writer
OutputFormat string
Height int64
@ -45,18 +46,18 @@ type CLIContext struct {
SkipConfirm bool
}
// NewCLIContextWithFrom returns a new initialized CLIContext with parameters from the
// command line using Viper. It takes a key name or address and populates the FromName and
// FromAddress field accordingly. It will also create Tendermint verifier using
// the chain ID, home directory and RPC URI provided by the command line. If using
// a CLIContext in tests or any non CLI-based environment, the verifier will not
// be created and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithFrom(from string) CLIContext {
// NewCLIContextWithInputAndFrom returns a new initialized CLIContext with parameters from the
// command line using Viper. It takes a io.Reader and and key name or address and populates
// the FromName and FromAddress field accordingly. It will also create Tendermint verifier
// using the chain ID, home directory and RPC URI provided by the command line. If using
// a CLIContext in tests or any non CLI-based environment, the verifier will not be created
// and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext {
var nodeURI string
var rpc rpcclient.Client
genOnly := viper.GetBool(flags.FlagGenerateOnly)
fromAddress, fromName, err := GetFromFields(from, genOnly)
fromAddress, fromName, err := GetFromFields(input, from, genOnly)
if err != nil {
fmt.Printf("failed to get from fields: %v", err)
os.Exit(1)
@ -72,6 +73,7 @@ func NewCLIContextWithFrom(from string) CLIContext {
ctx := CLIContext{
Client: rpc,
ChainID: viper.GetString(flags.FlagChainID),
Input: input,
Output: os.Stdout,
NodeURI: nodeURI,
From: viper.GetString(flags.FlagFrom),
@ -99,10 +101,32 @@ func NewCLIContextWithFrom(from string) CLIContext {
return ctx.WithVerifier(verifier)
}
// NewCLIContextWithFrom returns a new initialized CLIContext with parameters from the
// command line using Viper. It takes a key name or address and populates the FromName and
// FromAddress field accordingly. It will also create Tendermint verifier using
// the chain ID, home directory and RPC URI provided by the command line. If using
// a CLIContext in tests or any non CLI-based environment, the verifier will not
// be created and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithFrom(from string) CLIContext {
return NewCLIContextWithInputAndFrom(os.Stdin, from)
}
// NewCLIContext returns a new initialized CLIContext with parameters from the
// command line using Viper.
func NewCLIContext() CLIContext { return NewCLIContextWithFrom(viper.GetString(flags.FlagFrom)) }
// NewCLIContextWithInput returns a new initialized CLIContext with a io.Reader and parameters
// from the command line using Viper.
func NewCLIContextWithInput(input io.Reader) CLIContext {
return NewCLIContextWithInputAndFrom(input, viper.GetString(flags.FlagFrom))
}
// WithInput returns a copy of the context with an updated input.
func (ctx CLIContext) WithInput(r io.Reader) CLIContext {
ctx.Input = r
return ctx
}
// WithCodec returns a copy of the context with an updated codec.
func (ctx CLIContext) WithCodec(cdc *codec.Codec) CLIContext {
ctx.Codec = cdc
@ -229,7 +253,7 @@ func (ctx CLIContext) PrintOutput(toPrint interface{}) error {
// GetFromFields returns a from account address and Keybase name given either
// an address or key name. If genOnly is true, only a valid Bech32 cosmos
// address is returned.
func GetFromFields(from string, genOnly bool) (sdk.AccAddress, string, error) {
func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, string, error) {
if from == "" {
return nil, "", nil
}
@ -243,7 +267,7 @@ func GetFromFields(from string, genOnly bool) (sdk.AccAddress, string, error) {
return addr, "", nil
}
keybase, err := keys.NewKeyBaseFromHomeFlag()
keybase, err := keys.NewKeyringFromHomeFlag(input)
if err != nil {
return nil, "", err
}

View File

@ -87,7 +87,6 @@ output
func runAddCmd(cmd *cobra.Command, args []string) error {
var kb keys.Keybase
var err error
var encryptPassword string
inBuf := bufio.NewReader(cmd.InOrStdin())
name := args[0]
@ -99,9 +98,8 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
// we throw this away, so don't enforce args,
// we want to get a new random seed phrase quickly
kb = keys.NewInMemory()
encryptPassword = DefaultKeyPass
} else {
kb, err = NewKeyBaseFromHomeFlag()
kb, err = NewKeyringFromHomeFlag(cmd.InOrStdin())
if err != nil {
return err
}
@ -150,16 +148,6 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
cmd.PrintErrf("Key %q saved to disk.\n", name)
return nil
}
// ask for a password when generating a local key
if viper.GetString(FlagPublicKey) == "" && !viper.GetBool(flags.FlagUseLedger) {
encryptPassword, err = input.GetCheckPassword(
"Enter a passphrase to encrypt your key to disk:",
"Repeat the passphrase:", inBuf)
if err != nil {
return err
}
}
}
if viper.GetString(FlagPublicKey) != "" {
@ -243,7 +231,7 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
}
}
info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, encryptPassword, account, index)
info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, DefaultKeyPass, account, index)
if err != nil {
return err
}

View File

@ -6,7 +6,7 @@ import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/cli"
@ -17,6 +17,7 @@ import (
)
func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
runningUnattended := isRunningUnattended()
config := sdk.GetConfig()
bech32PrefixAccAddr := "terra"
@ -33,11 +34,11 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
config.SetBech32PrefixForConsensusNode(bech32PrefixConsAddr, bech32PrefixConsPub)
cmd := addKeyCommand()
assert.NotNil(t, cmd)
require.NotNil(t, cmd)
// Prepare a keybase
kbHome, kbCleanUp := tests.NewTestCaseDir(t)
assert.NotNil(t, kbHome)
require.NotNil(t, kbHome)
defer kbCleanUp()
viper.Set(flags.FlagHome, kbHome)
viper.Set(flags.FlagUseLedger, true)
@ -47,19 +48,26 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
// Now enter password
mockIn, _, _ := tests.ApplyMockIO(cmd)
mockIn.Reset("test1234\ntest1234\n")
assert.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
require.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
// Now check that it has been stored properly
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
assert.NotNil(t, kb)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
require.NotNil(t, kb)
defer func() {
kb.Delete("keyname1", "", false)
}()
mockIn.Reset("test1234\n")
if runningUnattended {
mockIn.Reset("test1234\ntest1234\n")
}
key1, err := kb.Get("keyname1")
assert.NoError(t, err)
assert.NotNil(t, key1)
require.NoError(t, err)
require.NotNil(t, key1)
assert.Equal(t, "keyname1", key1.GetName())
assert.Equal(t, keys.TypeLedger, key1.GetType())
assert.Equal(t,
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, keys.TypeLedger, key1.GetType())
require.Equal(t,
"terrapub1addwnpepqvpg7r26nl2pvqqern00m6s9uaax3hauu2rzg8qpjzq9hy6xve7sw0d84m6",
sdk.MustBech32ifyAccPub(key1.GetPubKey()))
@ -71,12 +79,14 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
}
func Test_runAddCmdLedger(t *testing.T) {
runningUnattended := isRunningUnattended()
cmd := addKeyCommand()
assert.NotNil(t, cmd)
require.NotNil(t, cmd)
mockIn, _, _ := tests.ApplyMockIO(cmd)
// Prepare a keybase
kbHome, kbCleanUp := tests.NewTestCaseDir(t)
assert.NotNil(t, kbHome)
require.NotNil(t, kbHome)
defer kbCleanUp()
viper.Set(flags.FlagHome, kbHome)
viper.Set(flags.FlagUseLedger, true)
@ -84,21 +94,27 @@ func Test_runAddCmdLedger(t *testing.T) {
/// Test Text
viper.Set(cli.OutputFlag, OutputFormatText)
// Now enter password
mockIn, _, _ := tests.ApplyMockIO(cmd)
mockIn.Reset("test1234\ntest1234\n")
assert.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
require.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
// Now check that it has been stored properly
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
assert.NotNil(t, kb)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
require.NotNil(t, kb)
defer func() {
kb.Delete("keyname1", "", false)
}()
mockIn.Reset("test1234\n")
if runningUnattended {
mockIn.Reset("test1234\ntest1234\n")
}
key1, err := kb.Get("keyname1")
assert.NoError(t, err)
assert.NotNil(t, key1)
require.NoError(t, err)
require.NotNil(t, key1)
assert.Equal(t, "keyname1", key1.GetName())
assert.Equal(t, keys.TypeLedger, key1.GetType())
assert.Equal(t,
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, keys.TypeLedger, key1.GetType())
require.Equal(t,
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
sdk.MustBech32ifyAccPub(key1.GetPubKey()))
}

View File

@ -5,6 +5,7 @@ import (
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/cli"
@ -13,6 +14,7 @@ import (
)
func Test_runAddCmdBasic(t *testing.T) {
runningUnattended := isRunningUnattended()
cmd := addKeyCommand()
assert.NotNil(t, cmd)
mockIn, _, _ := tests.ApplyMockIO(cmd)
@ -21,28 +23,33 @@ func Test_runAddCmdBasic(t *testing.T) {
assert.NotNil(t, kbHome)
defer kbCleanUp()
viper.Set(flags.FlagHome, kbHome)
viper.Set(cli.OutputFlag, OutputFormatText)
mockIn.Reset("test1234\ntest1234\n")
err := runAddCmd(cmd, []string{"keyname1"})
assert.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
} else {
mockIn.Reset("y\n")
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
defer func() {
kb.Delete("keyname1", "", false)
kb.Delete("keyname2", "", false)
}()
}
assert.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
viper.Set(cli.OutputFlag, OutputFormatText)
if runningUnattended {
mockIn.Reset("testpass1\nN\n")
} else {
mockIn.Reset("N\n")
}
assert.Error(t, runAddCmd(cmd, []string{"keyname1"}))
mockIn.Reset("test1234\ntest1234\n")
err = runAddCmd(cmd, []string{"keyname1"})
assert.Error(t, err)
viper.Set(cli.OutputFlag, OutputFormatText)
mockIn.Reset("y\ntest1234\ntest1234\n")
err = runAddCmd(cmd, []string{"keyname1"})
assert.NoError(t, err)
viper.Set(cli.OutputFlag, OutputFormatJSON)
mockIn.Reset("test1234\ntest1234\n")
err = runAddCmd(cmd, []string{"keyname2"})
if runningUnattended {
mockIn.Reset("testpass1\nN\n")
} else {
mockIn.Reset("y\n")
}
err := runAddCmd(cmd, []string{"keyname2"})
assert.NoError(t, err)
}

View File

@ -4,12 +4,11 @@ import (
"bufio"
"errors"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
@ -40,8 +39,9 @@ private keys stored in a ledger device cannot be deleted with the CLI.
func runDeleteCmd(cmd *cobra.Command, args []string) error {
name := args[0]
buf := bufio.NewReader(cmd.InOrStdin())
kb, err := NewKeyBaseFromHomeFlag()
kb, err := NewKeyringFromHomeFlag(buf)
if err != nil {
return err
}
@ -51,13 +51,14 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
return err
}
buf := bufio.NewReader(cmd.InOrStdin())
if info.GetType() == keys.TypeLedger || info.GetType() == keys.TypeOffline {
// confirm deletion, unless -y is passed
if !viper.GetBool(flagYes) {
if err := confirmDeletion(buf); err != nil {
return err
}
}
if err := kb.Delete(name, "", true); err != nil {
return err
}
@ -65,18 +66,8 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
return nil
}
// skip passphrase check if run with --force
skipPass := viper.GetBool(flagForce)
var oldpass string
if !skipPass {
if oldpass, err = input.GetPassword(
"DANGER - enter password to permanently delete key:", buf); err != nil {
return err
}
}
err = kb.Delete(name, oldpass, skipPass)
if err != nil {
// old password and skip flag arguments are ignored
if err := kb.Delete(name, "", true); err != nil {
return err
}
cmd.PrintErrln("Key deleted forever (uh oh!)")

View File

@ -6,7 +6,6 @@ import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -14,45 +13,74 @@ import (
)
func Test_runDeleteCmd(t *testing.T) {
runningUnattended := isRunningUnattended()
deleteKeyCommand := deleteKeyCommand()
mockIn, _, _ := tests.ApplyMockIO(deleteKeyCommand)
yesF, _ := deleteKeyCommand.Flags().GetBool(flagYes)
forceF, _ := deleteKeyCommand.Flags().GetBool(flagForce)
assert.False(t, yesF)
assert.False(t, forceF)
require.False(t, yesF)
require.False(t, forceF)
fakeKeyName1 := "runDeleteCmd_Key1"
fakeKeyName2 := "runDeleteCmd_Key2"
if !runningUnattended {
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
defer func() {
kb.Delete("runDeleteCmd_Key1", "", false)
kb.Delete("runDeleteCmd_Key2", "", false)
}()
}
// Now add a temporary keybase
kbHome, cleanUp := tests.NewTestCaseDir(t)
defer cleanUp()
viper.Set(flags.FlagHome, kbHome)
// Now
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
assert.NoError(t, err)
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
assert.NoError(t, err)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
err = runDeleteCmd(deleteKeyCommand, []string{"blah"})
require.Error(t, err)
require.Equal(t, "Key blah not found", err.Error())
require.Equal(t, "The specified item could not be found in the keyring", err.Error())
// User confirmation missing
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})
require.Error(t, err)
require.Equal(t, "EOF", err.Error())
if runningUnattended {
require.Equal(t, "aborted", err.Error())
} else {
require.Equal(t, "EOF", err.Error())
}
{
if runningUnattended {
mockIn.Reset("testpass1\n")
}
_, err = kb.Get(fakeKeyName1)
require.NoError(t, err)
// Now there is a confirmation
mockIn, _, _ := tests.ApplyMockIO(deleteKeyCommand)
mockIn.Reset("y\n")
viper.Set(flagYes, true)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
require.NoError(t, runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1}))
_, err = kb.Get(fakeKeyName1)
@ -60,14 +88,18 @@ func Test_runDeleteCmd(t *testing.T) {
}
viper.Set(flagYes, true)
if runningUnattended {
mockIn.Reset("testpass1\n")
}
_, err = kb.Get(fakeKeyName2)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ny\ntestpass1\n")
}
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName2})
require.NoError(t, err)
_, err = kb.Get(fakeKeyName2)
require.Error(t, err) // Key2 is gone
// TODO: Write another case for !keys.Local
}
func Test_confirmDeletion(t *testing.T) {

View File

@ -20,12 +20,12 @@ func exportKeyCommand() *cobra.Command {
}
func runExportCmd(cmd *cobra.Command, args []string) error {
kb, err := NewKeyBaseFromHomeFlag()
buf := bufio.NewReader(cmd.InOrStdin())
kb, err := NewKeyringFromHomeFlag(buf)
if err != nil {
return err
}
buf := bufio.NewReader(cmd.InOrStdin())
decryptPassword, err := input.GetPassword("Enter passphrase to decrypt your key:", buf)
if err != nil {
return err

View File

@ -4,14 +4,16 @@ import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/tests"
)
func Test_runExportCmd(t *testing.T) {
runningUnattended := isRunningUnattended()
exportKeyCommand := exportKeyCommand()
mockIn, _, _ := tests.ApplyMockIO(exportKeyCommand)
// Now add a temporary keybase
kbHome, cleanUp := tests.NewTestCaseDir(t)
@ -19,13 +21,25 @@ func Test_runExportCmd(t *testing.T) {
viper.Set(flags.FlagHome, kbHome)
// create a key
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
_, err = kb.CreateAccount("keyname1", tests.TestMnemonic, "", "123456789", 0, 0)
assert.NoError(t, err)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
if !runningUnattended {
defer func() {
kb.Delete("keyname1", "", false)
}()
}
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount("keyname1", tests.TestMnemonic, "", "123456789", 0, 0)
require.NoError(t, err)
mockIn, _, _ := tests.ApplyMockIO(exportKeyCommand)
mockIn.Reset("123456789\n123456789\n")
// Now enter password
assert.NoError(t, runExportCmd(exportKeyCommand, []string{"keyname1"}))
if runningUnattended {
mockIn.Reset("123456789\n123456789\ntestpass1\n")
} else {
mockIn.Reset("123456789\n123456789\n")
}
require.NoError(t, runExportCmd(exportKeyCommand, []string{"keyname1"}))
}

View File

@ -21,7 +21,8 @@ func importKeyCommand() *cobra.Command {
}
func runImportCmd(cmd *cobra.Command, args []string) error {
kb, err := NewKeyBaseFromHomeFlag()
buf := bufio.NewReader(cmd.InOrStdin())
kb, err := NewKeyringFromHomeFlag(buf)
if err != nil {
return err
}
@ -31,7 +32,6 @@ func runImportCmd(cmd *cobra.Command, args []string) error {
return err
}
buf := bufio.NewReader(cmd.InOrStdin())
passphrase, err := input.GetPassword("Enter passphrase to decrypt your key:", buf)
if err != nil {
return err

View File

@ -6,7 +6,6 @@ import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -14,13 +13,23 @@ import (
)
func Test_runImportCmd(t *testing.T) {
runningUnattended := isRunningUnattended()
importKeyCommand := importKeyCommand()
mockIn, _, _ := tests.ApplyMockIO(importKeyCommand)
// Now add a temporary keybase
kbHome, cleanUp := tests.NewTestCaseDir(t)
defer cleanUp()
viper.Set(flags.FlagHome, kbHome)
if !runningUnattended {
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
defer func() {
kb.Delete("keyname1", "", false)
}()
}
keyfile := filepath.Join(kbHome, "key.asc")
armoredKey := `-----BEGIN TENDERMINT PRIVATE KEY-----
salt: A790BB721D1C094260EA84F5E5B72289
@ -34,7 +43,10 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO
require.NoError(t, ioutil.WriteFile(keyfile, []byte(armoredKey), 0644))
// Now enter password
mockIn, _, _ := tests.ApplyMockIO(importKeyCommand)
mockIn.Reset("123456789\n")
assert.NoError(t, runImportCmd(importKeyCommand, []string{"keyname1", keyfile}))
if runningUnattended {
mockIn.Reset("123456789\n12345678\n12345678\n")
} else {
mockIn.Reset("123456789\n")
}
require.NoError(t, runImportCmd(importKeyCommand, []string{"keyname1", keyfile}))
}

View File

@ -19,7 +19,7 @@ along with their associated name and address.`,
}
func runListCmd(cmd *cobra.Command, args []string) error {
kb, err := NewKeyBaseFromHomeFlag()
kb, err := NewKeyringFromHomeFlag(cmd.InOrStdin())
if err != nil {
return err
}

View File

@ -5,13 +5,14 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/tests"
)
func Test_runListCmd(t *testing.T) {
runningUnattended := isRunningUnattended()
type args struct {
cmd *cobra.Command
args []string
@ -28,24 +29,34 @@ func Test_runListCmd(t *testing.T) {
defer cleanUp2()
viper.Set(flags.FlagHome, kbHome2)
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", 0, 0)
assert.NoError(t, err)
mockIn, _, _ := tests.ApplyMockIO(cmdBasic)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", 0, 0)
require.NoError(t, err)
defer func() {
kb.Delete("something", "", false)
}()
testData := []struct {
name string
kbDir string
args args
wantErr bool
}{
{"invalid keybase", "/dev/null", args{cmdBasic, []string{}}, true},
{"keybase: empty", kbHome1, args{cmdBasic, []string{}}, false},
{"keybase: w/key", kbHome2, args{cmdBasic, []string{}}, false},
}
for _, tt := range testData {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
viper.Set(flags.FlagHome, tt.kbDir)
if err := runListCmd(tt.args.cmd, tt.args.args); (err != nil) != tt.wantErr {
t.Errorf("runListCmd() error = %v, wantErr %v", err, tt.wantErr)

View File

@ -56,15 +56,19 @@ consisting of all the keys provided by name and multisig threshold.`,
func runShowCmd(cmd *cobra.Command, args []string) (err error) {
var info keys.Info
kb, err := NewKeyringFromHomeFlag(cmd.InOrStdin())
if err != nil {
return err
}
if len(args) == 1 {
info, err = GetKeyInfo(args[0])
info, err = kb.Get(args[0])
if err != nil {
return err
}
} else {
pks := make([]tmcrypto.PubKey, len(args))
for i, keyName := range args {
info, err := GetKeyInfo(keyName)
info, err := kb.Get(keyName)
if err != nil {
return err
}

View File

@ -4,7 +4,7 @@ import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/multisig"
@ -21,27 +21,25 @@ func Test_multiSigKey_Properties(t *testing.T) {
pk := multisig.NewPubKeyMultisigThreshold(1, []crypto.PubKey{tmpKey1.PubKey()})
tmp := keys.NewMultiInfo("myMultisig", pk)
assert.Equal(t, "myMultisig", tmp.GetName())
assert.Equal(t, keys.TypeMulti, tmp.GetType())
assert.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", tmp.GetPubKey().Address().String())
assert.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", tmp.GetAddress().String())
require.Equal(t, "myMultisig", tmp.GetName())
require.Equal(t, keys.TypeMulti, tmp.GetType())
require.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", tmp.GetPubKey().Address().String())
require.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", tmp.GetAddress().String())
}
func Test_showKeysCmd(t *testing.T) {
cmd := showKeysCmd()
assert.NotNil(t, cmd)
assert.Equal(t, "false", cmd.Flag(FlagAddress).DefValue)
assert.Equal(t, "false", cmd.Flag(FlagPublicKey).DefValue)
require.NotNil(t, cmd)
require.Equal(t, "false", cmd.Flag(FlagAddress).DefValue)
require.Equal(t, "false", cmd.Flag(FlagPublicKey).DefValue)
}
func Test_runShowCmd(t *testing.T) {
runningUnattended := isRunningUnattended()
cmd := showKeysCmd()
err := runShowCmd(cmd, []string{"invalid"})
assert.EqualError(t, err, "Key invalid not found")
err = runShowCmd(cmd, []string{"invalid1", "invalid2"})
assert.EqualError(t, err, "Key invalid1 not found")
mockIn, _, _ := tests.ApplyMockIO(cmd)
require.EqualError(t, runShowCmd(cmd, []string{"invalid"}), "The specified item could not be found in the keyring")
require.EqualError(t, runShowCmd(cmd, []string{"invalid1", "invalid2"}), "The specified item could not be found in the keyring")
// Prepare a key base
// Now add a temporary keybase
@ -51,47 +49,76 @@ func Test_runShowCmd(t *testing.T) {
fakeKeyName1 := "runShowCmd_Key1"
fakeKeyName2 := "runShowCmd_Key2"
kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
kb, err := NewKeyringFromHomeFlag(mockIn)
require.NoError(t, err)
defer func() {
kb.Delete("runShowCmd_Key1", "", false)
kb.Delete("runShowCmd_Key2", "", false)
}()
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
assert.NoError(t, err)
require.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
assert.NoError(t, err)
require.NoError(t, err)
// Now try single key
err = runShowCmd(cmd, []string{fakeKeyName1})
assert.EqualError(t, err, "invalid Bech32 prefix encoding provided: ")
if runningUnattended {
mockIn.Reset("testpass1\n")
}
require.EqualError(t, runShowCmd(cmd, []string{fakeKeyName1}), "invalid Bech32 prefix encoding provided: ")
// Now try single key - set bech to acc
viper.Set(FlagBechPrefix, sdk.PrefixAccount)
err = runShowCmd(cmd, []string{fakeKeyName1})
assert.NoError(t, err)
if runningUnattended {
mockIn.Reset("testpass1\n")
}
require.NoError(t, runShowCmd(cmd, []string{fakeKeyName1}))
// Now try multisig key - set bech to acc
viper.Set(FlagBechPrefix, sdk.PrefixAccount)
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
assert.EqualError(t, err, "threshold must be a positive integer")
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
require.EqualError(t, runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2}), "threshold must be a positive integer")
// Now try multisig key - set bech to acc + threshold=2
viper.Set(FlagBechPrefix, sdk.PrefixAccount)
viper.Set(flagMultiSigThreshold, 2)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
assert.NoError(t, err)
require.NoError(t, err)
// Now try multisig key - set bech to acc + threshold=2
viper.Set(FlagBechPrefix, "acc")
viper.Set(FlagDevice, true)
viper.Set(flagMultiSigThreshold, 2)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
assert.EqualError(t, err, "the device flag (-d) can only be used for accounts stored in devices")
require.EqualError(t, err, "the device flag (-d) can only be used for accounts stored in devices")
viper.Set(FlagBechPrefix, "val")
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
assert.EqualError(t, err, "the device flag (-d) can only be used for accounts")
require.EqualError(t, err, "the device flag (-d) can only be used for accounts")
viper.Set(FlagPublicKey, true)
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
assert.EqualError(t, err, "the device flag (-d) can only be used for addresses not pubkeys")
require.EqualError(t, err, "the device flag (-d) can only be used for addresses not pubkeys")
// TODO: Capture stdout and compare
}
@ -148,7 +175,7 @@ func Test_getBechKeyOut(t *testing.T) {
}
if !tt.wantErr {
assert.NotNil(t, got)
require.NotNil(t, got)
}
// TODO: Still not possible to compare functions

View File

@ -12,8 +12,14 @@ func updateKeyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "update <name>",
Short: "Change the password used to protect private key",
RunE: runUpdateCmd,
Args: cobra.ExactArgs(1),
Deprecated: `it takes no effect with the new keyring
based backend and is provided only for backward compatibility with the
legacy LevelDB based backend.
Refer to your operating system's manual to learn how to change your
keyring's password.
`,
RunE: runUpdateCmd,
Args: cobra.ExactArgs(1),
}
return cmd
}

View File

@ -1,18 +1,19 @@
package keys
import (
"bufio"
"fmt"
"io"
"os"
"path/filepath"
"github.com/99designs/keyring"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/cli"
yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// available output formats.
@ -26,55 +27,6 @@ const (
type bechKeyOutFn func(keyInfo keys.Info) (keys.KeyOutput, error)
// GetKeyInfo returns key info for a given name. An error is returned if the
// keybase cannot be retrieved or getting the info fails.
func GetKeyInfo(name string) (keys.Info, error) {
keybase, err := NewKeyBaseFromHomeFlag()
if err != nil {
return nil, err
}
return keybase.Get(name)
}
// GetPassphrase returns a passphrase for a given name. It will first retrieve
// the key info for that name if the type is local, it'll fetch input from
// STDIN. Otherwise, an empty passphrase is returned. An error is returned if
// the key info cannot be fetched or reading from STDIN fails.
func GetPassphrase(name string) (string, error) {
var passphrase string
keyInfo, err := GetKeyInfo(name)
if err != nil {
return passphrase, err
}
// we only need a passphrase for locally stored keys
// TODO: (ref: #864) address security concerns
if keyInfo.GetType() == keys.TypeLocal {
passphrase, err = ReadPassphraseFromStdin(name)
if err != nil {
return passphrase, err
}
}
return passphrase, nil
}
// ReadPassphraseFromStdin attempts to read a passphrase from STDIN return an
// error upon failure.
func ReadPassphraseFromStdin(name string) (string, error) {
buf := bufio.NewReader(os.Stdin)
prompt := fmt.Sprintf("Password to sign with '%s':", name)
passphrase, err := input.GetPassword(prompt, buf)
if err != nil {
return passphrase, fmt.Errorf("error reading passphrase: %v", err)
}
return passphrase, nil
}
// NewKeyBaseFromHomeFlag initializes a Keybase based on the configuration.
func NewKeyBaseFromHomeFlag() (keys.Keybase, error) {
rootDir := viper.GetString(flags.FlagHome)
@ -89,6 +41,19 @@ func NewKeyBaseFromDir(rootDir string) (keys.Keybase, error) {
// NewInMemoryKeyBase returns a storage-less keybase.
func NewInMemoryKeyBase() keys.Keybase { return keys.NewInMemory() }
// NewKeyBaseFromHomeFlag initializes a keyring based on configuration.
func NewKeyringFromHomeFlag(input io.Reader) (keys.Keybase, error) {
return NewKeyringFromDir(viper.GetString(flags.FlagHome), input)
}
// NewKeyBaseFromDir initializes a keybase at a particular dir.
func NewKeyringFromDir(rootDir string, input io.Reader) (keys.Keybase, error) {
if os.Getenv("COSMOS_SDK_TEST_KEYRING") != "" {
return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir)
}
return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input)
}
func getLazyKeyBaseFromDir(rootDir string) (keys.Keybase, error) {
return keys.New(defaultKeyDBName, filepath.Join(rootDir, "keys")), nil
}
@ -171,3 +136,8 @@ func printPubKey(info keys.Info, bechKeyOut bechKeyOutFn) {
fmt.Println(ko.PubKey)
}
func isRunningUnattended() bool {
backends := keyring.AvailableBackends()
return len(backends) == 2 && backends[1] == keyring.BackendType("file")
}

View File

@ -370,7 +370,7 @@ func (kb keyringKeybase) ImportPubKey(name string, armor string) error {
// deleting it (for security). It returns an error if the key doesn't exist or
// passphrases don't match. The passphrase is ignored when deleting references to
// offline and Ledger / HW wallet keys.
func (kb keyringKeybase) Delete(name, passphrase string, skipPass bool) error {
func (kb keyringKeybase) Delete(name, _ string, _ bool) error {
// verify we have the proper password before deleting
info, err := kb.Get(name)
if err != nil {

View File

@ -34,13 +34,14 @@ To generate a new key (default secp256k1 elliptic curve):
gaiacli keys add <your_key_name>
```
You will be asked to create a password (at least 8 characters) for this key-pair. This will return the information listed below:
The key-pair will be created in your system's password store. This will return the information listed below:
- `NAME`: Name of your key
- `TYPE`: Type of your key, always `local`.
- `ADDRESS`: Your address. Used to receive funds.
- `PUBKEY`: Your public key. Useful for validators.
- `MNEMONIC`: 24-words phrase. **Save this mnemonic somewhere safe**. It is used to recover your private key in case you forget the password.
- `MNEMONIC`: 24-words phrase. **Save this mnemonic somewhere safe**. It is used to recover your
private key in case you forget the password to unlock your system's credentials store.
You can see all your available keys by typing:

View File

@ -25,21 +25,13 @@ func GenerateCoinKey() (sdk.AccAddress, string, error) {
// GenerateSaveCoinKey returns the address of a public key, along with the secret
// phrase to recover the private key.
func GenerateSaveCoinKey(clientRoot, keyName, keyPass string,
overwrite bool) (sdk.AccAddress, string, error) {
// get the keystore from the client
keybase, err := clkeys.NewKeyBaseFromDir(clientRoot)
if err != nil {
return sdk.AccAddress([]byte{}), "", err
}
func GenerateSaveCoinKey(keybase keys.Keybase, keyName, keyPass string, overwrite bool) (sdk.AccAddress, string, error) {
// ensure no overwrite
if !overwrite {
_, err := keybase.Get(keyName)
if err == nil {
return sdk.AccAddress([]byte{}), "", fmt.Errorf(
"key already exists, overwrite is disabled (clientRoot: %s)", clientRoot)
"key already exists, overwrite is disabled")
}
}

View File

@ -1,14 +1,14 @@
package server_test
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/keys"
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/tests"
)
func TestGenerateCoinKey(t *testing.T) {
@ -24,17 +24,16 @@ func TestGenerateCoinKey(t *testing.T) {
func TestGenerateSaveCoinKey(t *testing.T) {
t.Parallel()
dir, cleanup := tempdir(t)
dir, cleanup := tests.NewTestCaseDir(t)
defer cleanup() // clean after itself
// Remove the dir to that GenerateSaveCoinKey creates it automatically
os.RemoveAll(dir)
addr, mnemonic, err := server.GenerateSaveCoinKey(dir, "keyname", "012345678", false)
kb, err := crkeys.NewTestKeyring(t.Name(), dir)
require.NoError(t, err)
addr, mnemonic, err := server.GenerateSaveCoinKey(kb, "keyname", "012345678", false)
require.NoError(t, err)
// Test key was actually saved
kb, err := keys.NewKeyBaseFromDir(dir)
require.NoError(t, err)
info, err := kb.Get("keyname")
require.NoError(t, err)
require.Equal(t, addr, info.GetAddress())
@ -47,28 +46,23 @@ func TestGenerateSaveCoinKey(t *testing.T) {
func TestGenerateSaveCoinKeyOverwriteFlag(t *testing.T) {
t.Parallel()
dir, cleanup := tempdir(t)
dir, cleanup := tests.NewTestCaseDir(t)
defer cleanup() // clean after itself
// Remove the dir to that GenerateSaveCoinKey creates it automatically
os.RemoveAll(dir)
kb, err := crkeys.NewTestKeyring(t.Name(), dir)
require.NoError(t, err)
keyname := "justakey"
addr1, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", false)
addr1, _, err := server.GenerateSaveCoinKey(kb, keyname, "012345678", false)
require.NoError(t, err)
// Test overwrite with overwrite=false
_, _, err = server.GenerateSaveCoinKey(dir, keyname, "012345678", false)
_, _, err = server.GenerateSaveCoinKey(kb, keyname, "012345678", false)
require.Error(t, err)
// Test overwrite with overwrite=true
addr2, _, err := server.GenerateSaveCoinKey(dir, keyname, "012345678", true)
addr2, _, err := server.GenerateSaveCoinKey(kb, keyname, "012345678", true)
require.NoError(t, err)
require.NotEqual(t, addr1, addr2)
}
func tempdir(t *testing.T) (string, func()) {
dir, err := ioutil.TempDir("", t.Name()+"_")
require.NoError(t, err)
return dir, func() { os.RemoveAll(dir) }
}

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"io/ioutil"
"os"
@ -65,7 +66,8 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
return
}
keybase, err := keys.NewKeyBaseFromDir(viper.GetString(cli.HomeFlag))
inBuf := bufio.NewReader(cmd.InOrStdin())
keybase, err := keys.NewKeyringFromDir(viper.GetString(cli.HomeFlag), inBuf)
if err != nil {
return
}
@ -80,8 +82,8 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
cliCtx := context.NewCLIContext().WithCodec(cdc)
txBldr := types.NewTxBuilderFromCLI()
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
txBldr := types.NewTxBuilderFromCLI(inBuf)
if !viper.GetBool(flagOffline) {
accnum, seq, err := types.NewAccountRetriever(cliCtx).GetAccountNumberSequence(multisigInfo.GetAddress())

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"os"
"strings"
@ -98,9 +99,10 @@ func makeSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string) error
return err
}
inBuf := bufio.NewReader(cmd.InOrStdin())
offline := viper.GetBool(flagOffline)
cliCtx := context.NewCLIContext().WithCodec(cdc)
txBldr := types.NewTxBuilderFromCLI()
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
txBldr := types.NewTxBuilderFromCLI(inBuf)
if viper.GetBool(flagValidateSigs) {
if !printAndValidateSigs(cliCtx, txBldr.ChainID(), stdTx, offline) {

View File

@ -10,10 +10,10 @@ import (
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -93,13 +93,8 @@ func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLICon
}
}
passphrase, err := keys.GetPassphrase(fromName)
if err != nil {
return err
}
// build and sign the transaction
txBytes, err := txBldr.BuildAndSign(fromName, passphrase, msgs)
txBytes, err := txBldr.BuildAndSign(fromName, client.DefaultKeyPass, msgs)
if err != nil {
return err
}
@ -197,12 +192,7 @@ func SignStdTx(
}
}
passphrase, err := keys.GetPassphrase(name)
if err != nil {
return signedStdTx, err
}
return txBldr.SignStdTx(name, passphrase, stdTx, appendSig)
return txBldr.SignStdTx(name, client.DefaultKeyPass, stdTx, appendSig)
}
// SignStdTxWithSignerAddress attaches a signature to a StdTx and returns a copy of a it.
@ -224,12 +214,7 @@ func SignStdTxWithSignerAddress(txBldr authtypes.TxBuilder, cliCtx context.CLICo
}
}
passphrase, err := keys.GetPassphrase(name)
if err != nil {
return signedStdTx, err
}
return txBldr.SignStdTx(name, passphrase, stdTx, false)
return txBldr.SignStdTx(name, client.DefaultKeyPass, stdTx, false)
}
// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin.

View File

@ -3,6 +3,8 @@ package types
import (
"errors"
"fmt"
"io"
"os"
"strings"
"github.com/spf13/viper"
@ -51,8 +53,8 @@ func NewTxBuilder(
// NewTxBuilderFromCLI returns a new initialized TxBuilder with parameters from
// the command line using Viper.
func NewTxBuilderFromCLI() TxBuilder {
kb, err := keys.NewKeyBaseFromHomeFlag()
func NewTxBuilderFromCLI(input io.Reader) TxBuilder {
kb, err := keys.NewKeyringFromHomeFlag(input)
if err != nil {
panic(err)
}
@ -274,7 +276,7 @@ func (bldr TxBuilder) SignStdTx(name, passphrase string, stdTx StdTx, appendSig
func MakeSignature(keybase crkeys.Keybase, name, passphrase string,
msg StdSignMsg) (sig StdSignature, err error) {
if keybase == nil {
keybase, err = keys.NewKeyBaseFromHomeFlag()
keybase, err = keys.NewKeyringFromHomeFlag(os.Stdin)
if err != nil {
return
}

View File

@ -1,6 +1,8 @@
package cli
import (
"bufio"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
@ -34,8 +36,9 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
Short: "Create and sign a send tx",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithFrom(args[0]).WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithCodec(cdc)
to, err := sdk.AccAddressFromBech32(args[1])
if err != nil {

View File

@ -2,6 +2,8 @@
package cli
import (
"bufio"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
@ -21,8 +23,9 @@ func GetCmdInvariantBroken(cdc *codec.Codec) *cobra.Command {
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
senderAddr := cliCtx.GetFromAddress()
moduleName, route := args[0], args[1]

View File

@ -2,6 +2,7 @@
package cli
import (
"bufio"
"fmt"
"strings"
@ -101,8 +102,9 @@ $ %s tx distr withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqh
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
delAddr := cliCtx.GetFromAddress()
valAddr, err := sdk.ValAddressFromBech32(args[0])
@ -138,8 +140,9 @@ $ %s tx distr withdraw-all-rewards --from mykey
),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
delAddr := cliCtx.GetFromAddress()
@ -180,8 +183,9 @@ $ %s tx set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from m
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
delAddr := cliCtx.GetFromAddress()
withdrawAddr, err := sdk.AccAddressFromBech32(args[0])
@ -232,8 +236,9 @@ Where proposal.json contains:
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
proposal, err := ParseCommunityPoolSpendProposalJSON(cdc, args[0])
if err != nil {

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
@ -94,7 +95,8 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm
return errors.Wrap(err, "failed to validate genesis state")
}
kb, err := client.NewKeyBaseFromDir(viper.GetString(flagClientHome))
inBuf := bufio.NewReader(cmd.InOrStdin())
kb, err := client.NewKeyringFromDir(viper.GetString(flagClientHome), inBuf)
if err != nil {
return errors.Wrap(err, "failed to initialize keybase")
}
@ -121,8 +123,8 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm
return errors.Wrap(err, "failed to validate account in genesis")
}
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := client.NewCLIContext().WithCodec(cdc)
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := client.NewCLIContextWithInput(inBuf).WithCodec(cdc)
// Set the generate-only flag here after the CLI context has
// been created. This allows the from name/key to be correctly populated.

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"strconv"
"strings"
@ -106,8 +107,9 @@ $ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome pr
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
proposal, err := parseSubmitProposalFlags()
if err != nil {
@ -156,8 +158,9 @@ $ %s tx gov deposit 1 10stake --from mykey
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
// validate that the proposal id is a uint
proposalID, err := strconv.ParseUint(args[0], 10, 64)
@ -203,8 +206,9 @@ $ %s tx gov vote 1 yes --from mykey
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
// Get voting address
from := cliCtx.GetFromAddress()

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"strings"
@ -64,8 +65,9 @@ Where proposal.json contains:
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
proposal, err := paramscutils.ParseParamChangeProposalJSON(cdc, args[0])
if err != nil {

View File

@ -1,6 +1,8 @@
package cli
import (
"bufio"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
@ -40,8 +42,9 @@ func GetCmdUnjail(cdc *codec.Codec) *cobra.Command {
$ <appcli> tx slashing unjail --from mykey
`,
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
valAddr := cliCtx.GetFromAddress()

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"os"
"strings"
@ -49,8 +50,9 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
Use: "create-validator",
Short: "create new validator initialized with a self-delegation to it",
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
txBldr, msg, err := BuildCreateValidatorMsg(cliCtx, txBldr)
if err != nil {
@ -85,8 +87,9 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
Use: "edit-validator",
Short: "edit an existing validator account",
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
valAddr := cliCtx.GetFromAddress()
description := types.NewDescription(
@ -150,8 +153,9 @@ $ %s tx staking delegate cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 10
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
amount, err := sdk.ParseCoin(args[1])
if err != nil {
@ -186,8 +190,9 @@ $ %s tx staking redelegate cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
delAddr := cliCtx.GetFromAddress()
valSrcAddr, err := sdk.ValAddressFromBech32(args[0])
@ -227,8 +232,9 @@ $ %s tx staking unbond cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100s
),
),
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(auth.DefaultTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
delAddr := cliCtx.GetFromAddress()
valAddr, err := sdk.ValAddressFromBech32(args[0])

View File

@ -1,6 +1,7 @@
package cli
import (
"bufio"
"fmt"
"time"
@ -85,8 +86,9 @@ func GetCmdSubmitUpgradeProposal(cdc *codec.Codec) *cobra.Command {
return err
}
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
from := cliCtx.GetFromAddress()
depositStr, err := cmd.Flags().GetString(cli.FlagDeposit)
@ -124,8 +126,9 @@ func GetCmdSubmitCancelUpgradeProposal(cdc *codec.Codec) *cobra.Command {
Short: "Submit a software upgrade proposal",
Long: "Cancel a software upgrade along with an initial deposit.",
RunE: func(cmd *cobra.Command, args []string) error {
txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
from := cliCtx.GetFromAddress()
depositStr, err := cmd.Flags().GetString(cli.FlagDeposit)