diff --git a/CHANGELOG.md b/CHANGELOG.md index 65a1ac801c..6a51fa017f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (third_party/proto) [\#1037](https://github.com/Finschia/finschia-sdk/pull/1037) change the proof.proto path to third_party/proto/confio * (ostracon) [\#1057](https://github.com/Finschia/finschia-sdk/pull/1057) Bump up Ostracon from to v1.1.1 * (docs) [\#1120](https://github.com/Finschia/finschia-sdk/pull/1120) Update links in x/foundation README.md +* (feat) [\#1121](https://github.com/Finschia/finschia-sdk/pull/1121) Add update-censorship cmd to x/foundation cli ### Bug Fixes * (ledger) [\#1040](https://github.com/Finschia/finschia-sdk/pull/1040) fix a bug(unable to connect nano S plus ledger on ubuntu) diff --git a/x/foundation/client/cli/tx.go b/x/foundation/client/cli/tx.go index bc4eddad12..e654e0f887 100644 --- a/x/foundation/client/cli/tx.go +++ b/x/foundation/client/cli/tx.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "strconv" + "strings" "github.com/spf13/cobra" @@ -91,6 +92,22 @@ func execFromString(execStr string) foundation.Exec { return exec } +func normalizeCensorshipAuthority(option string) string { + prefix := getEnumPrefix(foundation.CensorshipAuthority_name[0]) + candidate := strings.ToUpper(prefix + option) + if _, ok := foundation.CensorshipAuthority_value[candidate]; ok { + return candidate + } + + return option +} + +func getEnumPrefix(str string) string { + delimiter := "_" + splitted := strings.Split(str, delimiter) + return strings.Join(splitted[:len(splitted)-1], delimiter) + delimiter +} + // VoteOptionFromString returns a VoteOption from a string. It returns an error // if the string is invalid. func voteOptionFromString(str string) (foundation.VoteOption, error) { @@ -101,6 +118,15 @@ func voteOptionFromString(str string) (foundation.VoteOption, error) { return foundation.VoteOption(vo), nil } +// CensorshipAuthorityFromString returns a CensorshipAuthority from a string. It returns an error if the string is invalid. +func censorshipAuthorityFromString(str string) (foundation.CensorshipAuthority, error) { + ca, ok := foundation.CensorshipAuthority_value[str] + if !ok { + return foundation.CensorshipAuthorityUnspecified, fmt.Errorf("'%s' is not a valid censorship authority", str) + } + return foundation.CensorshipAuthority(ca), nil +} + func parseMsgs(cdc codec.Codec, msgsJSON string) ([]sdk.Msg, error) { var cliMsgs []json.RawMessage if err := json.Unmarshal([]byte(msgsJSON), &cliMsgs); err != nil { @@ -549,6 +575,54 @@ func NewTxCmdExec() *cobra.Command { return cmd } +func NewTxCmdUpdateCensorship() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-censorship [authority] [msg-type-url] [new-authority]", + Args: cobra.ExactArgs(3), + Short: "Update censorship over a message", + Long: `Update censorship over a message + +Parameters: + authority: the current authority of the censorship + msg-type-url: the message type url of the censorship + new-authority: a new authority of the censorship + unspecified: no authority, which means removing the censorship + governance: x/gov + foundation: x/foundation +`, + RunE: func(cmd *cobra.Command, args []string) error { + if err := validateGenerateOnly(cmd); err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + newAuthority, err := censorshipAuthorityFromString(normalizeCensorshipAuthority(args[2])) + if err != nil { + return err + } + + msg := foundation.MsgUpdateCensorship{ + Authority: args[0], + Censorship: foundation.Censorship{ + MsgTypeUrl: args[1], + Authority: newAuthority, + }, + } + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + func NewTxCmdLeaveFoundation() *cobra.Command { cmd := &cobra.Command{ Use: "leave-foundation [address]", diff --git a/x/foundation/client/testutil/tx.go b/x/foundation/client/testutil/tx.go index 36f7169dc6..ccc283cb8c 100644 --- a/x/foundation/client/testutil/tx.go +++ b/x/foundation/client/testutil/tx.go @@ -420,6 +420,69 @@ func (s *IntegrationTestSuite) TestNewTxCmdExec() { } } +func (s *IntegrationTestSuite) TestNewTxCmdUpdateCensorship() { + val := s.network.Validators[0] + commonArgs := []string{ + fmt.Sprintf("--%s", flags.FlagGenerateOnly), + } + + testCases := map[string]struct { + args []string + valid bool + }{ + "valid transaction": { + []string{ + s.authority.String(), + foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(), + foundation.CensorshipAuthorityGovernance.String(), + }, + true, + }, + "valid abbreviation": { + []string{ + s.authority.String(), + foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(), + "governance", + }, + true, + }, + "wrong number of args": { + []string{ + s.authority.String(), + foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(), + foundation.CensorshipAuthorityGovernance.String(), + "extra", + }, + false, + }, + "invalid new authority": { + []string{ + s.authority.String(), + foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(), + "invalid-new-authority", + }, + false, + }, + } + + for name, tc := range testCases { + tc := tc + + s.Run(name, func() { + cmd := cli.NewTxCmdUpdateCensorship() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, append(tc.args, commonArgs...)) + if !tc.valid { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + var res txtypes.Tx + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res), out) + }) + } +} + func (s *IntegrationTestSuite) TestNewTxCmdLeaveFoundation() { val := s.network.Validators[0] commonArgs := []string{