Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client/keys): add support for importing hex key using standard input #24071

Open
wants to merge 4 commits into
base: release/v0.53.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (client/keys) [#24071](https://github.com/cosmos/cosmos-sdk/pull/24071) Add support for importing hex key using standard input.
* (perf)[#24045](https://github.com/cosmos/cosmos-sdk/pull/24045) Sims: Replace runsim command with Go stdlib testing. CLI: `Commit` default true, `Lean`, `SimulateEveryOperation`, `PrintAllInvariants`, `DBBackend` params removed
* (crypto/keyring) [#24040](https://github.com/cosmos/cosmos-sdk/pull/24040) Expose the db keyring used in the keystore.
* (types) [#23919](https://github.com/cosmos/cosmos-sdk/pull/23919) Add MustValAddressFromBech32 function.
Expand Down
31 changes: 26 additions & 5 deletions client/keys/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package keys

import (
"bufio"
"errors"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"

Expand All @@ -26,9 +28,13 @@ func ImportKeyCommand() *cobra.Command {
if err != nil {
return err
}
name := args[0]
if strings.TrimSpace(name) == "" {
return errors.New("the provided name is invalid or empty after trimming whitespace")
}
buf := bufio.NewReader(clientCtx.Input)

bz, err := os.ReadFile(args[1])
armor, err := os.ReadFile(args[1])
if err != nil {
return err
}
Expand All @@ -38,24 +44,39 @@ func ImportKeyCommand() *cobra.Command {
return err
}

return clientCtx.Keyring.ImportPrivKey(args[0], string(bz), passphrase)
return clientCtx.Keyring.ImportPrivKey(name, string(armor), passphrase)
},
}
}

func ImportKeyHexCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "import-hex <name> <hex>",
Use: "import-hex <name> [hex]",
Short: "Import private keys into the local keybase",
Long: fmt.Sprintf("Import hex encoded private key into the local keybase.\nSupported key-types can be obtained with:\n%s list-key-types", version.AppName),
Args: cobra.ExactArgs(2),
Args: cobra.RangeArgs(1, 2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
name := args[0]
if strings.TrimSpace(name) == "" {
return errors.New("the provided name is invalid or empty after trimming whitespace")
}

keyType, _ := cmd.Flags().GetString(flags.FlagKeyType)
return clientCtx.Keyring.ImportPrivKeyHex(args[0], args[1], keyType)
var hexKey string
if len(args) == 2 {
hexKey = args[1]
} else {
buf := bufio.NewReader(clientCtx.Input)
hexKey, err = input.GetPassword("Enter hex private key:", buf)
if err != nil {
return err
}
}
return clientCtx.Keyring.ImportPrivKeyHex(name, hexKey, keyType)
},
}
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "private key signing algorithm kind")
Expand Down
38 changes: 25 additions & 13 deletions client/keys/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO
// Now add a temporary keybase
kbHome := filepath.Join(t.TempDir(), fmt.Sprintf("kbhome-%s", tc.name))
// Create dir, otherwise os.WriteFile will fail
if _, err := os.Stat(kbHome); os.IsNotExist(err) {
err = os.MkdirAll(kbHome, 0o700)
require.NoError(t, err)
}
require.NoError(t, os.MkdirAll(kbHome, 0o700))
t.Cleanup(func() {
require.NoError(t, os.RemoveAll(kbHome))
})
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc)
require.NoError(t, err)

Expand Down Expand Up @@ -127,6 +127,7 @@ func Test_runImportHexCmd(t *testing.T) {
name string
keyringBackend string
hexKey string
stdInput bool
keyType string
expectError bool
}{
Expand All @@ -136,6 +137,13 @@ func Test_runImportHexCmd(t *testing.T) {
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
keyType: "secp256k1",
},
{
name: "read the hex key from standard input",
keyringBackend: keyring.BackendTest,
stdInput: true,
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
keyType: "secp256k1",
},
}

for _, tc := range testCases {
Expand All @@ -146,6 +154,10 @@ func Test_runImportHexCmd(t *testing.T) {

// Now add a temporary keybase
kbHome := filepath.Join(t.TempDir(), fmt.Sprintf("kbhome-%s", tc.name))
t.Cleanup(func() {
require.NoError(t, os.RemoveAll(kbHome))
})

kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc)
require.NoError(t, err)

Expand All @@ -156,17 +168,17 @@ func Test_runImportHexCmd(t *testing.T) {
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

t.Cleanup(cleanupKeys(t, kb, "keyname1"))

defer func() {
_ = os.RemoveAll(kbHome)
}()

cmd.SetArgs([]string{
"keyname1", tc.hexKey,
args := []string{"keyname1"}
if tc.stdInput {
mockIn.Reset(tc.hexKey)
} else {
args = append(args, tc.hexKey)
}
cmd.SetArgs(append(
args,
fmt.Sprintf("--%s=%s", flags.FlagKeyType, tc.keyType),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, tc.keyringBackend),
})
))

err = cmd.ExecuteContext(ctx)
if tc.expectError {
Expand Down
Loading