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): check multisig key duplicate #18703

Merged
merged 8 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dist
tools-stamp
buf-stamp
artifacts
simapp/simd/simd

# Go
go.work
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Improvements

* (client/keys) [#18703](https://github.com/cosmos/cosmos-sdk/pull/18703) Improve `<appd> keys add` and `<appd> keys show` by checking whether there are duplicate keys in the multisig case.
* (x/bank) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `SendCoinsFromModuleToAccount`, `SendCoinsFromModuleToModule`, `SendCoinsFromAccountToModule`, `DelegateCoinsFromAccountToModule`, `UndelegateCoinsFromModuleToAccount`, `MintCoins` and `BurnCoins` methods now returns an error instead of panicking if any module accounts does not exist or unauthorized.
* (x/distribution) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `CalculateDelegationRewards` and `DelegationTotalRewards` methods no longer panics on any sanity checks and instead returns appropriate errors.
* (x/slashing) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `JailUntil` and `Tombstone` methods no longer panics if the signing info does not exist for the validator but instead returns error.
Expand Down
10 changes: 8 additions & 2 deletions client/keys/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,14 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}

for i, keyname := range multisigKeys {
k, err := kb.Key(keyname)
keyFilter := make(map[string]struct{})
levisyin marked this conversation as resolved.
Show resolved Hide resolved
for i, keyName := range multisigKeys {
if _, ok := keyFilter[keyName]; ok {
levisyin marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("duplicate multisig keys: %s", keyName)
} else {
keyFilter[keyName] = struct{}{}
}
k, err := kb.Key(keyName)
if err != nil {
return err
}
Expand Down
71 changes: 71 additions & 0 deletions client/keys/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,77 @@ func Test_runAddCmdBasic(t *testing.T) {
require.Error(t, cmd.ExecuteContext(ctx))
}

func Test_runAddCmdMultisig(t *testing.T) {
levisyin marked this conversation as resolved.
Show resolved Hide resolved
cmd := AddKeyCommand()
cmd.Flags().AddFlagSet(Commands().PersistentFlags())

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

cdc := moduletestutil.MakeTestEncodingConfig().Codec
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)

clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithInput(mockIn).
WithCodec(cdc).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))

ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

t.Cleanup(func() {
_ = kb.Delete("keyname1")
_ = kb.Delete("keyname2")
_ = kb.Delete("multisigname")
})

cmd.SetArgs([]string{
"keyname1",
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.NoError(t, cmd.ExecuteContext(ctx))

cmd.SetArgs([]string{
"keyname2",
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.NoError(t, cmd.ExecuteContext(ctx))

cmd.SetArgs([]string{
"multisigname",
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", flagMultisig, "keyname1,keyname2"),
fmt.Sprintf("--%s=%s", flagMultiSigThreshold, "2"),
})
require.NoError(t, cmd.ExecuteContext(ctx))

cmd.SetArgs([]string{
"multisigname",
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagOutput, flags.OutputFormatText),
fmt.Sprintf("--%s=%s", flags.FlagKeyType, hd.Secp256k1Type),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", flagMultisig, "keyname1,keyname1"),
fmt.Sprintf("--%s=%s", flagMultiSigThreshold, "2"),
})
mockIn.Reset("y\n")
require.Error(t, cmd.ExecuteContext(ctx))
mockIn.Reset("y\n")
require.EqualError(t, cmd.ExecuteContext(ctx), "duplicate multisig keys: keyname1")
}

func Test_runAddCmdDryRun(t *testing.T) {
pubkey1 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtObiFVE4s+9+RX5SP8TN9r2mxpoaT4eGj9CJfK7VRzN"}`
pubkey2 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/se1vkqgdQ7VJQCM4mxN+L+ciGhnnJ4XYsQCRBMrdRi"}`
Expand Down
12 changes: 9 additions & 3 deletions client/keys/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,16 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
}
} else {
pks := make([]cryptotypes.PubKey, len(args))
for i, keyref := range args {
k, err := fetchKey(clientCtx.Keyring, keyref, clientCtx.AddressCodec)
keyFilter := make(map[string]struct{})
levisyin marked this conversation as resolved.
Show resolved Hide resolved
for i, keyRef := range args {
if _, ok := keyFilter[keyRef]; ok {
cmd.Printf("WARNING: duplicate keys found: %s.\n", keyRef)
levisyin marked this conversation as resolved.
Show resolved Hide resolved
levisyin marked this conversation as resolved.
Show resolved Hide resolved
} else {
keyFilter[keyRef] = struct{}{}
}
levisyin marked this conversation as resolved.
Show resolved Hide resolved
k, err := fetchKey(clientCtx.Keyring, keyRef, clientCtx.AddressCodec)
if err != nil {
return fmt.Errorf("%s is not a valid name or address: %w", keyref, err)
return fmt.Errorf("%s is not a valid name or address: %w", keyRef, err)
}
key, err := k.GetPubKey()
if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions client/keys/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ func Test_runShowCmd(t *testing.T) {
})
require.EqualError(t, cmd.ExecuteContext(ctx), "threshold must be a positive integer")

// Now try multisig key duplicate(we just show warning message instead of return error)
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName1,
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
fmt.Sprintf("--%s=%s", FlagBechPrefix, sdk.PrefixAccount),
fmt.Sprintf("--%s=2", flagMultiSigThreshold),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.NoError(t, cmd.ExecuteContext(ctx))
levisyin marked this conversation as resolved.
Show resolved Hide resolved

cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, kbHome),
Expand Down
Loading