diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb15bee3b..b80a0c60b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (cli) [#21372](https://github.com/cosmos/cosmos-sdk/pull/21372) Add a `bulk-add-genesis-account` genesis command to add many genesis accounts at once. * (crypto/keyring) [#21653](https://github.com/cosmos/cosmos-sdk/pull/21653) New Linux-only backend that adds Linux kernel's `keyctl` support. * (runtime) [#21704](https://github.com/cosmos/cosmos-sdk/pull/21704) Add StoreLoader in simappv2. +* (client/keys) [#21829](https://github.com/cosmos/cosmos-sdk/pull/21829) Add support for importing hex key using standard input. ### Improvements diff --git a/client/keys/import.go b/client/keys/import.go index 9a86da2879..c9893239ae 100644 --- a/client/keys/import.go +++ b/client/keys/import.go @@ -34,7 +34,7 @@ func ImportKeyCommand() *cobra.Command { } buf := bufio.NewReader(clientCtx.Input) - bz, err := os.ReadFile(args[1]) + armor, err := os.ReadFile(args[1]) if err != nil { return err } @@ -44,17 +44,17 @@ 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 ", + Use: "import-hex [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 { @@ -65,7 +65,17 @@ func ImportKeyHexCommand() *cobra.Command { 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") diff --git a/client/keys/import_test.go b/client/keys/import_test.go index bc9c5d34ab..3f73cbd965 100644 --- a/client/keys/import_test.go +++ b/client/keys/import_test.go @@ -82,11 +82,11 @@ 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) @@ -97,15 +97,9 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO WithCodec(cdc) ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx) - t.Cleanup(cleanupKeys(t, kb, "keyname1")) - keyfile := filepath.Join(kbHome, "key.asc") require.NoError(t, os.WriteFile(keyfile, []byte(armoredKey), 0o600)) - defer func() { - _ = os.RemoveAll(kbHome) - }() - mockIn.Reset(tc.userInput) cmd.SetArgs([]string{ "keyname1", keyfile, @@ -128,6 +122,7 @@ func Test_runImportHexCmd(t *testing.T) { name string keyringBackend string hexKey string + stdInput bool keyType string expectError bool }{ @@ -137,6 +132,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 { @@ -147,6 +149,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) @@ -157,17 +163,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 {