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: Add MsgLeaveGroup to group module #10887

Merged
merged 52 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
1a890f6
feat: add proto definitions
aleem1314 Jan 5, 2022
212613a
feat: implement msg
aleem1314 Jan 20, 2022
bad6dc0
WIP: msg server
aleem1314 Jan 20, 2022
e662c5f
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Jan 20, 2022
085fa8a
WIP: implementing msg server
aleem1314 Jan 21, 2022
dff0bdb
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Jan 21, 2022
c458296
chore: run make proto-gen
aleem1314 Jan 21, 2022
e470c66
feat: add cli
aleem1314 Jan 21, 2022
d877e54
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Jan 21, 2022
90306c1
wip: integration tests
aleem1314 Jan 24, 2022
2f2f9df
feat: add cli tests
aleem1314 Jan 24, 2022
6c166cb
chore: fix test
aleem1314 Jan 24, 2022
cce7b03
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Jan 24, 2022
8f9bfb6
feat: add simulation
aleem1314 Jan 24, 2022
932dcf3
chore: cleanup
aleem1314 Jan 26, 2022
70ce88c
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Jan 26, 2022
387a093
refactor: remove policy_addr
aleem1314 Feb 7, 2022
aba070c
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 7, 2022
206ed22
make proto-gen
aleem1314 Feb 7, 2022
90acf02
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 11, 2022
edf16de
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 15, 2022
fd33f93
chore: run make proto-gen
aleem1314 Feb 15, 2022
c04f98c
chore: review changes
aleem1314 Feb 15, 2022
23e0783
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 23, 2022
61f5fd5
make proto-gen
aleem1314 Feb 23, 2022
a635fd7
Update x/group/client/testutil/tx.go
aleem1314 Feb 23, 2022
8bacac7
review changes
aleem1314 Feb 23, 2022
28eee80
Merge branch 'aleem/9657-msg-leave-group' of https://github.com/cosmo…
aleem1314 Feb 23, 2022
2247cc8
update error check
aleem1314 Feb 23, 2022
c1814fd
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 25, 2022
4a28b90
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 28, 2022
51f370e
Update x/group/msgs.go
aleem1314 Feb 28, 2022
9f6f30b
fix imports
aleem1314 Feb 28, 2022
4cee605
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Feb 28, 2022
f9b4c5a
Update x/group/client/cli/tx.go
aleem1314 Mar 2, 2022
1988cbc
make proto-gen
aleem1314 Mar 2, 2022
0e64917
Merge branch 'aleem/9657-msg-leave-group' into aleem/9657-msg-leave-g…
aleem1314 Mar 2, 2022
277cd05
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Mar 2, 2022
ad889b7
make proto-gen
aleem1314 Mar 2, 2022
62e7672
fix tests
aleem1314 Mar 2, 2022
237b574
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Mar 3, 2022
bef38db
chore: add test
aleem1314 Mar 3, 2022
413dbeb
fix test
aleem1314 Mar 3, 2022
7e61240
review changes
aleem1314 Mar 4, 2022
2addb63
chore: fix cli test
aleem1314 Mar 4, 2022
d9eb60a
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Mar 4, 2022
e95daee
review changes
aleem1314 Mar 4, 2022
997e4a4
Merge branch 'aleem/9657-msg-leave-group' into aleem/9657-msg-leave-g…
aleem1314 Mar 4, 2022
0d23961
fix cli test
aleem1314 Mar 4, 2022
bb29821
Merge branch 'master' into aleem/9657-msg-leave-group
aleem1314 Mar 4, 2022
ea82a8c
Update x/group/spec/03_messages.md
aleem1314 Mar 4, 2022
a4bfd0c
Merge branch 'master' into aleem/9657-msg-leave-group
mergify[bot] Mar 4, 2022
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
569 changes: 551 additions & 18 deletions api/cosmos/group/v1beta1/events.pulsar.go

Large diffs are not rendered by default.

1,207 changes: 1,073 additions & 134 deletions api/cosmos/group/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions api/cosmos/group/v1beta1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions proto/cosmos/group/v1beta1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@ message EventExec {
// proposal_id is the unique ID of the proposal.
uint64 proposal_id = 1;
}

// EventLeaveGroup is an event emitted when group member leaves the group.
message EventLeaveGroup {

// group_id is the unique ID of the group.
uint64 group_id = 1;
aleem1314 marked this conversation as resolved.
Show resolved Hide resolved

// address is the account address of the group member.
string address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}
17 changes: 17 additions & 0 deletions proto/cosmos/group/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ service Msg {

// Exec executes a proposal.
rpc Exec(MsgExec) returns (MsgExecResponse);

// LeaveGroup allows a group member to leave the group.
rpc LeaveGroup(MsgLeaveGroup) returns (MsgLeaveGroupResponse);
}

//
Expand Down Expand Up @@ -345,3 +348,17 @@ message MsgExec {

// MsgExecResponse is the Msg/Exec request type.
message MsgExecResponse {}

// MsgLeaveGroup is the Msg/LeaveGroup request type.
message MsgLeaveGroup {
aleem1314 marked this conversation as resolved.
Show resolved Hide resolved
option (cosmos.msg.v1.signer) = "address";

// address is the account address of the group member.
string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// group_id is the unique ID of the group.
uint64 group_id = 2;
}

// MsgLeaveGroupResponse is the Msg/LeaveGroup response type.
message MsgLeaveGroupResponse {}
44 changes: 44 additions & 0 deletions x/group/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TxCmd(name string) *cobra.Command {
MsgSubmitProposalCmd(),
MsgVoteCmd(),
MsgExecCmd(),
MsgLeaveGroupCmd(),
)

return txCmd
Expand Down Expand Up @@ -780,3 +781,46 @@ func MsgExecCmd() *cobra.Command {

return cmd
}

// MsgLeaveGroupCmd creates a CLI command for Msg/LeaveGroup.
func MsgLeaveGroupCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "leave-group [member-address] [group-id]",
Short: "remove member from the group",
Long: ` remove member from the group

Parameters:
group-id: unique id of the group
member-address: account address of the group member
Note, the '--from' flag is
ignored as it is implied from [member-address]
`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Flags().Set(flags.FlagFrom, args[0])
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

groupID, err := strconv.ParseUint(args[1], 10, 64)
if err != nil {
return err
}

msg := &group.MsgLeaveGroup{
Address: clientCtx.GetFromAddress().String(),
GroupId: groupID,
}
if err = msg.ValidateBasic(); err != nil {
return fmt.Errorf("message validation failed: %w", err)
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
187 changes: 187 additions & 0 deletions x/group/client/testutil/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2108,6 +2108,193 @@ func (s *IntegrationTestSuite) TestTxExec() {
}
}

func (s *IntegrationTestSuite) TestTxLeaveGroup() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx
require := s.Require()

commonFlags := []string{
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
}

// create 3 accounts with some tokens
members := make([]string, 3)
for i := 1; i <= 3; i++ {
info, _, err := clientCtx.Keyring.NewMnemonic(fmt.Sprintf("member%d", i), keyring.English, sdk.FullFundraiserPath,
keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(err)

pk, err := info.GetPubKey()
require.NoError(err)

account := sdk.AccAddress(pk.Address())
members[i-1] = account.String()

_, err = banktestutil.MsgSendExec(clientCtx, val.Address, account,
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(100))),
commonFlags...,
)
require.NoError(err)
}

// create a group with three members
validMembers := fmt.Sprintf(`{"members": [{
"address": "%s",
"weight": "1",
"metadata": "AQ=="
},{
"address": "%s",
"weight": "2",
"metadata": "AQ=="
},{
"address": "%s",
"weight": "2",
"metadata": "AQ=="
}]}`, members[0], members[1], members[2])
validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers)
out, err := cli.ExecTestCLICmd(clientCtx, client.MsgCreateGroupCmd(),
append(
[]string{
val.Address.String(),
validMetadata,
validMembersFile.Name(),
},
commonFlags...,
),
)
require.NoError(err, out.String())
var txResp sdk.TxResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String())
groupID := s.getGroupIdFromTxResponse(txResp)

// create group policy
out, err = cli.ExecTestCLICmd(clientCtx, client.MsgCreateGroupPolicyCmd(),
append(
[]string{
val.Address.String(),
groupID,
"AQ==",
"{\"@type\":\"/cosmos.group.v1beta1.ThresholdDecisionPolicy\", \"threshold\":\"3\", \"windows\":{\"voting_period\":\"1s\"}}",
},
commonFlags...,
),
)
require.NoError(err, out.String())

out, err = cli.ExecTestCLICmd(clientCtx, client.QueryGroupPoliciesByGroupCmd(), []string{groupID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)})
require.NoError(err, out.String())
require.NotNil(out)
var resp group.QueryGroupPoliciesByGroupResponse
require.NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp))
require.Len(resp.GroupPolicies, 1)

testCases := []struct {
name string
args []string
expectErr bool
errMsg string
}{
{
"invalid member address",
append(
[]string{
"address",
groupID,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
},
commonFlags...,
),
true,
"key not found",
},
{
"group not found",
append(
[]string{
members[0],
"40",
fmt.Sprintf("--%s=%s", flags.FlagFrom, members[0]),
},
commonFlags...,
),
true,
"group: not found",
},
{
"valid case",
append(
[]string{
members[2],
groupID,
fmt.Sprintf("--%s=%s", flags.FlagFrom, members[2]),
},
commonFlags...,
),
false,
"",
},
{
"not part of group",
append(
[]string{
members[2],
groupID,
fmt.Sprintf("--%s=%s", flags.FlagFrom, members[2]),
},
commonFlags...,
),
true,
"is not part of group",
},
{
"can leave group policy threshold is more than group weight",
append(
[]string{
members[1],
groupID,
fmt.Sprintf("--%s=%s", flags.FlagFrom, members[1]),
},
commonFlags...,
),
false,
"",
},
}

for _, tc := range testCases {
tc := tc

s.Run(tc.name, func() {
cmd := client.MsgLeaveGroupCmd()
out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
require.Contains(out.String(), tc.errMsg)
} else {
require.NoError(err, out.String())
var resp sdk.TxResponse
require.NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
}
})
}
}

func (s *IntegrationTestSuite) getGroupIdFromTxResponse(txResp sdk.TxResponse) string {
s.Require().Greater(len(txResp.Logs), 0)
s.Require().NotNil(txResp.Logs[0].Events)
events := txResp.Logs[0].Events
createProposalEvent, _ := sdk.TypedEventToEvent(&group.EventCreateGroup{})

for _, e := range events {
if e.Type == createProposalEvent.Type {
return strings.ReplaceAll(e.Attributes[0].Value, "\"", "")
}
}

return ""
}

// createCLIProposal writes a CLI proposal with a MsgSend to a file. Returns
// the path to the JSON file.
func (s *IntegrationTestSuite) createCLIProposal(groupPolicyAddress, proposer, sendFrom, sendTo, metadata string) string {
Expand Down
2 changes: 2 additions & 0 deletions x/group/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgWithdrawProposal{}, "cosmos-sdk/group/MsgWithdrawProposal", nil)
cdc.RegisterConcrete(&MsgVote{}, "cosmos-sdk/group/MsgVote", nil)
cdc.RegisterConcrete(&MsgExec{}, "cosmos-sdk/group/MsgExec", nil)
cdc.RegisterConcrete(&MsgLeaveGroup{}, "cosmos-sdk/group/MsgLeaveGroup", nil)
}

func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
aleem1314 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -45,6 +46,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
&MsgWithdrawProposal{},
&MsgVote{},
&MsgExec{},
&MsgLeaveGroup{},
)

msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
Expand Down
Loading