Skip to content

Commit 22ef4b8

Browse files
mergify[bot]daeMOn63
authored andcommitted
fix: file keyring fails to add/import/export keys when input is not stdin (fix cosmos#9566) (cosmos#9821) (cosmos#9881)
## Description Add a test case to reproduce the issue described in cosmos#9566. The test currently fails, and I've pointed some possible solutions over cosmos#9566 (comment). But I feel this needs more works in order to provide a more robust solution. I'll keep poking at better options, but taking any pointers if anyone has ideas. (cherry picked from commit f479b51) Co-authored-by: daeMOn <[email protected]>
1 parent 4a32ead commit 22ef4b8

File tree

5 files changed

+57
-187
lines changed

5 files changed

+57
-187
lines changed

client/context.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package client
22

33
import (
44
"bufio"
5-
"context"
65
"encoding/json"
76
"fmt"
87
"io"
@@ -107,12 +106,23 @@ func (ctx Context) WithKeyringOptions(opts ...keyring.Option) Context {
107106
// WithInput returns a copy of the context with an updated input.
108107
func (ctx Context) WithInput(r io.Reader) Context {
109108
// convert to a bufio.Reader to have a shared buffer between the keyring and the
110-
// Commands, ensuring a read from one advance the read pointer for the other.
109+
// the Commands, ensuring a read from one advance the read pointer for the other.
111110
// see https://github.com/cosmos/cosmos-sdk/issues/9566.
112111
ctx.Input = bufio.NewReader(r)
113112
return ctx
114113
}
115114

115+
// Deprecated: WithJSONCodec returns a copy of the Context with an updated JSONCodec.
116+
func (ctx Context) WithJSONCodec(m codec.JSONCodec) Context {
117+
ctx.JSONCodec = m
118+
// since we are using ctx.Codec everywhere in the SDK, for backward compatibility
119+
// we need to try to set it here as well.
120+
if c, ok := m.(codec.Codec); ok {
121+
ctx.Codec = c
122+
}
123+
return ctx
124+
}
125+
116126
// WithCodec returns a copy of the Context with an updated Codec.
117127
func (ctx Context) WithCodec(m codec.Codec) Context {
118128
ctx.Codec = m

client/keys/add_test.go

+10-25
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"github.com/cosmos/cosmos-sdk/testutil"
2020
"github.com/cosmos/cosmos-sdk/testutil/testdata"
2121
sdk "github.com/cosmos/cosmos-sdk/types"
22-
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
22+
bip39 "github.com/cosmos/go-bip39"
2323
)
2424

2525
func Test_runAddCmdBasic(t *testing.T) {
@@ -33,14 +33,7 @@ func Test_runAddCmdBasic(t *testing.T) {
3333
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
3434
require.NoError(t, err)
3535

36-
clientCtx := client.Context{}.
37-
WithKeyringDir(kbHome).
38-
WithInput(mockIn).
39-
WithCodec(cdc).
40-
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
41-
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
42-
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))
43-
36+
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn)
4437
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
4538

4639
t.Cleanup(func() {
@@ -348,27 +341,19 @@ func Test_runAddCmdDryRun(t *testing.T) {
348341

349342
func TestAddRecoverFileBackend(t *testing.T) {
350343
cmd := AddKeyCommand()
351-
cmd.Flags().AddFlagSet(Commands().PersistentFlags())
352-
cdc := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}).Codec
344+
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
353345

354346
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
355347
kbHome := t.TempDir()
356348

357-
clientCtx := client.Context{}.
358-
WithKeyringDir(kbHome).
359-
WithInput(mockIn).
360-
WithCodec(cdc).
361-
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
362-
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
363-
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))
364-
349+
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn)
365350
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
366351

367352
cmd.SetArgs([]string{
368353
"keyname1",
369-
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
370-
fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
371-
fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
354+
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
355+
fmt.Sprintf("--%s=%s", cli.OutputFlag, OutputFormatText),
356+
fmt.Sprintf("--%s=%s", flags.FlagKeyAlgorithm, string(hd.Secp256k1Type)),
372357
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendFile),
373358
fmt.Sprintf("--%s", flagRecover),
374359
})
@@ -384,7 +369,7 @@ func TestAddRecoverFileBackend(t *testing.T) {
384369
mockIn.Reset(fmt.Sprintf("%s\n%s\n%s\n", mnemonic, keyringPassword, keyringPassword))
385370
require.NoError(t, cmd.ExecuteContext(ctx))
386371

387-
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendFile, kbHome, mockIn, cdc)
372+
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendFile, kbHome, mockIn)
388373
require.NoError(t, err)
389374

390375
t.Cleanup(func() {
@@ -393,7 +378,7 @@ func TestAddRecoverFileBackend(t *testing.T) {
393378
})
394379

395380
mockIn.Reset(fmt.Sprintf("%s\n%s\n", keyringPassword, keyringPassword))
396-
k, err := kb.Key("keyname1")
381+
info, err := kb.Key("keyname1")
397382
require.NoError(t, err)
398-
require.Equal(t, "keyname1", k.Name)
383+
require.Equal(t, "keyname1", info.GetName())
399384
}

client/keys/export_test.go

+19-40
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@ import (
2020
)
2121

2222
func Test_runExportCmd(t *testing.T) {
23-
cdc := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}).Codec
2423
testCases := []struct {
25-
name string
26-
keyringBackend string
27-
extraArgs []string
28-
userInput string
29-
mustFail bool
30-
expectedOutput string
31-
expectedOutputContain string // only valid when expectedOutput is empty
24+
name string
25+
keyringBackend string
26+
extraArgs []string
27+
userInput string
28+
mustFail bool
29+
expectedOutput string
3230
}{
3331
{
3432
name: "--unsafe only must fail",
@@ -51,33 +49,17 @@ func Test_runExportCmd(t *testing.T) {
5149
expectedOutput: "",
5250
},
5351
{
54-
name: "--unsafe --unarmored-hex --yes success",
55-
keyringBackend: keyring.BackendTest,
56-
extraArgs: []string{"--unsafe", "--unarmored-hex", "--yes"},
57-
userInput: "",
58-
mustFail: false,
59-
expectedOutputContain: "2485e33678db4175dc0ecef2d6e1fc493d4a0d7f7ce83324b6ed70afe77f3485\n",
60-
},
61-
{
62-
name: "--unsafe --unarmored-hex success",
63-
keyringBackend: keyring.BackendTest,
64-
extraArgs: []string{"--unsafe", "--unarmored-hex"},
65-
userInput: "y\n",
66-
mustFail: false,
67-
expectedOutputContain: "2485e33678db4175dc0ecef2d6e1fc493d4a0d7f7ce83324b6ed70afe77f3485\n",
68-
},
69-
{
70-
name: "--unsafe --unarmored-hex --indiscreet success",
52+
name: "--unsafe --unarmored-hex succeed",
7153
keyringBackend: keyring.BackendTest,
72-
extraArgs: []string{"--unsafe", "--unarmored-hex", "--indiscreet"},
54+
extraArgs: []string{"--unsafe", "--unarmored-hex"},
7355
userInput: "y\n",
7456
mustFail: false,
7557
expectedOutput: "2485e33678db4175dc0ecef2d6e1fc493d4a0d7f7ce83324b6ed70afe77f3485\n",
7658
},
7759
{
7860
name: "file keyring backend properly read password and user confirmation",
7961
keyringBackend: keyring.BackendFile,
80-
extraArgs: []string{"--unsafe", "--unarmored-hex", "--indiscreet"},
62+
extraArgs: []string{"--unsafe", "--unarmored-hex"},
8163
// first 2 pass for creating the key, then unsafe export confirmation, then unlock keyring pass
8264
userInput: "12345678\n12345678\ny\n12345678\n",
8365
mustFail: false,
@@ -90,12 +72,12 @@ func Test_runExportCmd(t *testing.T) {
9072
kbHome := t.TempDir()
9173
defaultArgs := []string{
9274
"keyname1",
93-
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
75+
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
9476
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, tc.keyringBackend),
9577
}
9678

9779
cmd := ExportKeyCommand()
98-
cmd.Flags().AddFlagSet(Commands().PersistentFlags())
80+
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
9981

10082
cmd.SetArgs(append(defaultArgs, tc.extraArgs...))
10183
mockIn, mockOut := testutil.ApplyMockIO(cmd)
@@ -104,31 +86,28 @@ func Test_runExportCmd(t *testing.T) {
10486
mockInBuf := bufio.NewReader(mockIn)
10587

10688
// create a key
107-
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, bufio.NewReader(mockInBuf), cdc)
89+
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, bufio.NewReader(mockInBuf))
10890
require.NoError(t, err)
109-
t.Cleanup(cleanupKeys(t, kb, "keyname1"))
91+
t.Cleanup(func() {
92+
kb.Delete("keyname1") // nolint:errcheck
93+
})
11094

111-
path := sdk.GetFullBIP44Path()
112-
_, err = kb.NewAccount("keyname1", testdata.TestMnemonic, "", path, hd.Secp256k1)
95+
path := sdk.GetConfig().GetFullBIP44Path()
96+
_, err = kb.NewAccount("keyname1", testutil.TestMnemonic, "", path, hd.Secp256k1)
11397
require.NoError(t, err)
11498

11599
clientCtx := client.Context{}.
116100
WithKeyringDir(kbHome).
117101
WithKeyring(kb).
118-
WithInput(mockInBuf).
119-
WithCodec(cdc)
102+
WithInput(mockInBuf)
120103
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
121104

122105
err = cmd.ExecuteContext(ctx)
123106
if tc.mustFail {
124107
require.Error(t, err)
125108
} else {
126109
require.NoError(t, err)
127-
if tc.expectedOutput != "" {
128-
require.Equal(t, tc.expectedOutput, mockOut.String())
129-
} else if tc.expectedOutputContain != "" {
130-
require.Contains(t, mockOut.String(), tc.expectedOutputContain)
131-
}
110+
require.Equal(t, tc.expectedOutput, mockOut.String())
132111
}
133112
})
134113
}

client/keys/import.go

-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ func ImportKeyCommand() *cobra.Command {
2828
if err != nil {
2929
return err
3030
}
31-
name := args[0]
32-
if strings.TrimSpace(name) == "" {
33-
return errors.New("the provided name is invalid or empty after trimming whitespace")
34-
}
3531
buf := bufio.NewReader(clientCtx.Input)
3632

3733
armor, err := os.ReadFile(args[1])

0 commit comments

Comments
 (0)