github.com/cosmos/cosmos-sdk@v0.50.10/client/keys/add_test.go (about)

     1  package keys
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  	"testing"
     9  
    10  	"github.com/cosmos/go-bip39"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/cosmos/cosmos-sdk/client"
    14  	"github.com/cosmos/cosmos-sdk/client/flags"
    15  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    16  	"github.com/cosmos/cosmos-sdk/crypto/keyring"
    17  	"github.com/cosmos/cosmos-sdk/testutil"
    18  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    19  	sdk "github.com/cosmos/cosmos-sdk/types"
    20  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    21  )
    22  
    23  func Test_runAddCmdBasic(t *testing.T) {
    24  	cmd := AddKeyCommand()
    25  	cmd.Flags().AddFlagSet(Commands().PersistentFlags())
    26  
    27  	mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
    28  	kbHome := t.TempDir()
    29  
    30  	cdc := moduletestutil.MakeTestEncodingConfig().Codec
    31  	kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
    32  	require.NoError(t, err)
    33  
    34  	clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
    35  	ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
    36  
    37  	t.Cleanup(func() {
    38  		_ = kb.Delete("keyname1")
    39  		_ = kb.Delete("keyname2")
    40  	})
    41  
    42  	cmd.SetArgs([]string{
    43  		"keyname1",
    44  		fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
    45  		fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
    46  		fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
    47  		fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
    48  	})
    49  	mockIn.Reset("y\n")
    50  	require.NoError(t, cmd.ExecuteContext(ctx))
    51  
    52  	mockIn.Reset("N\n")
    53  	require.Error(t, cmd.ExecuteContext(ctx))
    54  
    55  	cmd.SetArgs([]string{
    56  		"keyname2",
    57  		fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
    58  		fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
    59  		fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
    60  		fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
    61  	})
    62  
    63  	require.NoError(t, cmd.ExecuteContext(ctx))
    64  	require.Error(t, cmd.ExecuteContext(ctx))
    65  
    66  	mockIn.Reset("y\n")
    67  	require.NoError(t, cmd.ExecuteContext(ctx))
    68  
    69  	cmd.SetArgs([]string{
    70  		"keyname4",
    71  		fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
    72  		fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
    73  		fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
    74  		fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
    75  	})
    76  
    77  	require.NoError(t, cmd.ExecuteContext(ctx))
    78  	require.Error(t, cmd.ExecuteContext(ctx))
    79  
    80  	cmd.SetArgs([]string{
    81  		"keyname5",
    82  		fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
    83  		fmt.Sprintf("--%s=true", flags.FlagDryRun),
    84  		fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
    85  		fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
    86  	})
    87  
    88  	require.NoError(t, cmd.ExecuteContext(ctx))
    89  
    90  	// In recovery mode
    91  	cmd.SetArgs([]string{
    92  		"keyname6",
    93  		fmt.Sprintf("--%s=true", flagRecover),
    94  	})
    95  
    96  	// use valid mnemonic and complete recovery key generation successfully
    97  	mockIn.Reset("decide praise business actor peasant farm drastic weather extend front hurt later song give verb rhythm worry fun pond reform school tumble august one\n")
    98  	require.NoError(t, cmd.ExecuteContext(ctx))
    99  
   100  	// use invalid mnemonic and fail recovery key generation
   101  	mockIn.Reset("invalid mnemonic\n")
   102  	require.Error(t, cmd.ExecuteContext(ctx))
   103  
   104  	// In interactive mode
   105  	cmd.SetArgs([]string{
   106  		"keyname7",
   107  		"-i",
   108  		fmt.Sprintf("--%s=false", flagRecover),
   109  	})
   110  
   111  	const password = "password1!"
   112  
   113  	// set password and complete interactive key generation successfully
   114  	mockIn.Reset("\n" + password + "\n" + password + "\n")
   115  	require.NoError(t, cmd.ExecuteContext(ctx))
   116  
   117  	// passwords don't match and fail interactive key generation
   118  	mockIn.Reset("\n" + password + "\n" + "fail" + "\n")
   119  	require.Error(t, cmd.ExecuteContext(ctx))
   120  }
   121  
   122  func Test_runAddCmdDryRun(t *testing.T) {
   123  	pubkey1 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtObiFVE4s+9+RX5SP8TN9r2mxpoaT4eGj9CJfK7VRzN"}`
   124  	pubkey2 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/se1vkqgdQ7VJQCM4mxN+L+ciGhnnJ4XYsQCRBMrdRi"}`
   125  	b64Pubkey := "QWhnOHhpdXBJcGZ2UlR2ak5la1ExclROUThTOW96YjdHK2RYQmFLVjl4aUo="
   126  	cdc := moduletestutil.MakeTestEncodingConfig().Codec
   127  
   128  	testData := []struct {
   129  		name  string
   130  		args  []string
   131  		added bool
   132  	}{
   133  		{
   134  			name: "account is added",
   135  			args: []string{
   136  				"testkey",
   137  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "false"),
   138  			},
   139  			added: true,
   140  		},
   141  		{
   142  			name: "account is not added with dry run",
   143  			args: []string{
   144  				"testkey",
   145  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "true"),
   146  			},
   147  			added: false,
   148  		},
   149  		{
   150  			name: "multisig account is added",
   151  			args: []string{
   152  				"testkey",
   153  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "false"),
   154  				fmt.Sprintf("--%s=%s", flagMultisig, "subkey"),
   155  			},
   156  			added: true,
   157  		},
   158  		{
   159  			name: "multisig account is not added with dry run",
   160  			args: []string{
   161  				"testkey",
   162  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "true"),
   163  				fmt.Sprintf("--%s=%s", flagMultisig, "subkey"),
   164  			},
   165  			added: false,
   166  		},
   167  		{
   168  			name: "pubkey account is added",
   169  			args: []string{
   170  				"testkey",
   171  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "false"),
   172  				fmt.Sprintf("--%s=%s", FlagPublicKey, pubkey1),
   173  			},
   174  			added: true,
   175  		},
   176  		{
   177  			name: "pubkey account is not added with dry run",
   178  			args: []string{
   179  				"testkey",
   180  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "true"),
   181  				fmt.Sprintf("--%s=%s", FlagPublicKey, pubkey2),
   182  			},
   183  			added: false,
   184  		},
   185  		{
   186  			name: "base64 pubkey account is added",
   187  			args: []string{
   188  				"testkey",
   189  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "false"),
   190  				fmt.Sprintf("--%s=%s", flagPubKeyBase64, b64Pubkey),
   191  			},
   192  			added: true,
   193  		},
   194  		{
   195  			name: "base64 pubkey account is not added with dry run",
   196  			args: []string{
   197  				"testkey",
   198  				fmt.Sprintf("--%s=%s", flags.FlagDryRun, "true"),
   199  				fmt.Sprintf("--%s=%s", flagPubKeyBase64, b64Pubkey),
   200  			},
   201  			added: false,
   202  		},
   203  	}
   204  	for _, tt := range testData {
   205  		tt := tt
   206  		t.Run(tt.name, func(t *testing.T) {
   207  			cmd := AddKeyCommand()
   208  			cmd.Flags().AddFlagSet(Commands().PersistentFlags())
   209  
   210  			kbHome := t.TempDir()
   211  			mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
   212  
   213  			kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
   214  			require.NoError(t, err)
   215  
   216  			clientCtx := client.Context{}.
   217  				WithCodec(cdc).
   218  				WithKeyringDir(kbHome).
   219  				WithKeyring(kb)
   220  			ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
   221  
   222  			path := sdk.GetConfig().GetFullBIP44Path()
   223  			_, err = kb.NewAccount("subkey", testdata.TestMnemonic, "", path, hd.Secp256k1)
   224  			require.NoError(t, err)
   225  
   226  			t.Cleanup(func() {
   227  				_ = kb.Delete("subkey")
   228  			})
   229  
   230  			b := bytes.NewBufferString("")
   231  			cmd.SetOut(b)
   232  
   233  			cmd.SetArgs(tt.args)
   234  			require.NoError(t, cmd.ExecuteContext(ctx))
   235  
   236  			if tt.added {
   237  				_, err := kb.Key("testkey")
   238  				require.NoError(t, err)
   239  
   240  				out, err := io.ReadAll(b)
   241  				require.NoError(t, err)
   242  				require.Contains(t, string(out), "name: testkey")
   243  			} else {
   244  				_, err = kb.Key("testkey")
   245  				require.Error(t, err)
   246  				require.Equal(t, "testkey.info: key not found", err.Error())
   247  			}
   248  		})
   249  	}
   250  }
   251  
   252  func TestAddRecoverFileBackend(t *testing.T) {
   253  	cmd := AddKeyCommand()
   254  	cmd.Flags().AddFlagSet(Commands().PersistentFlags())
   255  	cdc := moduletestutil.MakeTestEncodingConfig().Codec
   256  
   257  	mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
   258  	kbHome := t.TempDir()
   259  
   260  	clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
   261  	ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
   262  
   263  	cmd.SetArgs([]string{
   264  		"keyname1",
   265  		fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
   266  		fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
   267  		fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
   268  		fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendFile),
   269  		fmt.Sprintf("--%s", flagRecover),
   270  	})
   271  
   272  	keyringPassword := "12345678"
   273  
   274  	entropySeed, err := bip39.NewEntropy(mnemonicEntropySize)
   275  	require.NoError(t, err)
   276  
   277  	mnemonic, err := bip39.NewMnemonic(entropySeed)
   278  	require.NoError(t, err)
   279  
   280  	mockIn.Reset(fmt.Sprintf("%s\n%s\n%s\n", mnemonic, keyringPassword, keyringPassword))
   281  	require.NoError(t, cmd.ExecuteContext(ctx))
   282  
   283  	kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendFile, kbHome, mockIn, cdc)
   284  	require.NoError(t, err)
   285  
   286  	t.Cleanup(func() {
   287  		mockIn.Reset(fmt.Sprintf("%s\n%s\n", keyringPassword, keyringPassword))
   288  		_ = kb.Delete("keyname1")
   289  	})
   290  
   291  	mockIn.Reset(fmt.Sprintf("%s\n%s\n", keyringPassword, keyringPassword))
   292  	k, err := kb.Key("keyname1")
   293  	require.NoError(t, err)
   294  	require.Equal(t, "keyname1", k.Name)
   295  }