feat: Add genesis import/export to group module (#10659)

## Description
Add genesis import/export and its related tests to group module.

Closes: #9900 



---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
likhita-809 2022-01-11 14:26:35 +05:30 committed by GitHub
parent d64253f98a
commit 9aef070625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 2026 additions and 47 deletions

View File

@ -0,0 +1,38 @@
syntax = "proto3";
package cosmos.group.v1beta1;
option go_package = "github.com/cosmos/cosmos-sdk/x/group";
import "cosmos/group/v1beta1/types.proto";
// GenesisState defines the group module's genesis state.
message GenesisState {
// group_seq is the group table orm.Sequence,
// it is used to get the next group ID.
uint64 group_seq = 1;
// groups is the list of groups info.
repeated GroupInfo groups = 2;
// group_members is the list of groups members.
repeated GroupMember group_members = 3;
// group_policy_account_seq is the group policy table orm.Sequence,
// it is used to generate the next group policy account address.
uint64 group_policy_account_seq = 4;
// group_policies is the list of group policies info.
repeated GroupPolicyInfo group_policies = 5;
// proposal_seq is the proposal table orm.Sequence,
// it is used to get the next proposal ID.
uint64 proposal_seq = 6;
// proposals is the list of proposals.
repeated Proposal proposals = 7;
// votes is the list of votes.
repeated Vote votes = 8;
}

View File

@ -361,18 +361,16 @@ func NewSimApp(
upgradetypes.ModuleName, capabilitytypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName,
authtypes.ModuleName, banktypes.ModuleName, govtypes.ModuleName, crisistypes.ModuleName, genutiltypes.ModuleName,
authz.ModuleName, feegrant.ModuleName, nft.ModuleName,
authz.ModuleName, feegrant.ModuleName, nft.ModuleName, group.ModuleName,
paramstypes.ModuleName, vestingtypes.ModuleName,
group.ModuleName,
)
app.mm.SetOrderEndBlockers(
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName,
slashingtypes.ModuleName, minttypes.ModuleName,
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
feegrant.ModuleName, nft.ModuleName,
feegrant.ModuleName, nft.ModuleName, group.ModuleName,
paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
group.ModuleName,
)
// NOTE: The genutils module must occur after staking so that pools are
@ -383,10 +381,9 @@ func NewSimApp(
app.mm.SetOrderInitGenesis(
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName,
slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName,
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, group.ModuleName,
feegrant.ModuleName, nft.ModuleName,
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
feegrant.ModuleName, nft.ModuleName, group.ModuleName,
paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
group.ModuleName,
)
// Uncomment if you want to set a custom migration order here.

View File

@ -28,6 +28,7 @@ import (
feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/gov"
group "github.com/cosmos/cosmos-sdk/x/group/module"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/slashing"
@ -179,6 +180,7 @@ func TestRunMigrations(t *testing.T) {
"distribution": distribution.AppModule{}.ConsensusVersion(),
"slashing": slashing.AppModule{}.ConsensusVersion(),
"gov": gov.AppModule{}.ConsensusVersion(),
"group": group.AppModule{}.ConsensusVersion(),
"params": params.AppModule{}.ConsensusVersion(),
"upgrade": upgrade.AppModule{}.ConsensusVersion(),
"vesting": vesting.AppModule{}.ConsensusVersion(),

View File

@ -390,7 +390,7 @@ func MsgUpdateGroupPolicyAdminCmd() *cobra.Command {
// MsgUpdateGroupPolicyDecisionPolicyCmd creates a CLI command for Msg/UpdateGroupPolicyDecisionPolicy.
func MsgUpdateGroupPolicyDecisionPolicyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update-group-account-policy [admin] [group-policy-account] [decision-policy]",
Use: "update-group-policy-decision-policy [admin] [group-policy-account] [decision-policy]",
Short: "Update a group policy's decision policy",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {

96
x/group/genesis.go Normal file
View File

@ -0,0 +1,96 @@
package group
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// NewGenesisState creates a new genesis state with default values.
func NewGenesisState() *GenesisState {
return &GenesisState{}
}
func (s GenesisState) Validate() error {
groups := make(map[uint64]GroupInfo)
groupPolicies := make(map[string]GroupPolicyInfo)
groupMembers := make(map[uint64]GroupMember)
proposals := make(map[uint64]Proposal)
for _, g := range s.Groups {
if err := g.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "Group validation failed")
}
groups[g.GroupId] = *g
}
for _, g := range s.GroupPolicies {
// check that group with group policy's GroupId exists
if _, exists := groups[g.GroupId]; !exists {
return sdkerrors.Wrap(sdkerrors.ErrNotFound, fmt.Sprintf("group with GroupId %d doesn't exist", g.GroupId))
}
if err := g.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "GroupPolicy validation failed")
}
groupPolicies[g.Address] = *g
}
for _, g := range s.GroupMembers {
// check that group with group member's GroupId exists
if _, exists := groups[g.GroupId]; !exists {
return sdkerrors.Wrap(sdkerrors.ErrNotFound, fmt.Sprintf("group member with GroupId %d doesn't exist", g.GroupId))
}
if err := g.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "GroupMember validation failed")
}
groupMembers[g.GroupId] = *g
}
for _, p := range s.Proposals {
// check that group policy with proposal address exists
if _, exists := groupPolicies[p.Address]; !exists {
return sdkerrors.Wrap(sdkerrors.ErrNotFound, fmt.Sprintf("group policy account with address %s doesn't correspond to proposal address", p.Address))
}
if err := p.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "Proposal validation failed")
}
proposals[p.ProposalId] = *p
}
for _, v := range s.Votes {
if err := v.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "Vote validation failed")
}
// check that proposal exists
if _, exists := proposals[v.ProposalId]; !exists {
return sdkerrors.Wrap(sdkerrors.ErrNotFound, fmt.Sprintf("proposal with ProposalId %d doesn't exist", v.ProposalId))
}
}
return nil
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (s GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error {
for _, g := range s.GroupPolicies {
err := g.UnpackInterfaces(unpacker)
if err != nil {
return err
}
}
for _, p := range s.Proposals {
err := p.UnpackInterfaces(unpacker)
if err != nil {
return err
}
}
return nil
}

705
x/group/genesis.pb.go Normal file
View File

@ -0,0 +1,705 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/group/v1beta1/genesis.proto
package group
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the group module's genesis state.
type GenesisState struct {
// group_seq is the group table orm.Sequence,
// it is used to get the next group ID.
GroupSeq uint64 `protobuf:"varint,1,opt,name=group_seq,json=groupSeq,proto3" json:"group_seq,omitempty"`
// groups is the list of groups info.
Groups []*GroupInfo `protobuf:"bytes,2,rep,name=groups,proto3" json:"groups,omitempty"`
// group_members is the list of groups members.
GroupMembers []*GroupMember `protobuf:"bytes,3,rep,name=group_members,json=groupMembers,proto3" json:"group_members,omitempty"`
// group_policy_account_seq is the group policy table orm.Sequence,
// it is used to generate the next group policy account address.
GroupPolicyAccountSeq uint64 `protobuf:"varint,4,opt,name=group_policy_account_seq,json=groupPolicyAccountSeq,proto3" json:"group_policy_account_seq,omitempty"`
// group_policies is the list of group policies info.
GroupPolicies []*GroupPolicyInfo `protobuf:"bytes,5,rep,name=group_policies,json=groupPolicies,proto3" json:"group_policies,omitempty"`
// proposal_seq is the proposal table orm.Sequence,
// it is used to get the next proposal ID.
ProposalSeq uint64 `protobuf:"varint,6,opt,name=proposal_seq,json=proposalSeq,proto3" json:"proposal_seq,omitempty"`
// proposals is the list of proposals.
Proposals []*Proposal `protobuf:"bytes,7,rep,name=proposals,proto3" json:"proposals,omitempty"`
// votes is the list of votes.
Votes []*Vote `protobuf:"bytes,8,rep,name=votes,proto3" json:"votes,omitempty"`
}
func (m *GenesisState) Reset() { *m = GenesisState{} }
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
func (*GenesisState) ProtoMessage() {}
func (*GenesisState) Descriptor() ([]byte, []int) {
return fileDescriptor_7eedba45e0e08e2c, []int{0}
}
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GenesisState) XXX_Merge(src proto.Message) {
xxx_messageInfo_GenesisState.Merge(m, src)
}
func (m *GenesisState) XXX_Size() int {
return m.Size()
}
func (m *GenesisState) XXX_DiscardUnknown() {
xxx_messageInfo_GenesisState.DiscardUnknown(m)
}
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
func (m *GenesisState) GetGroupSeq() uint64 {
if m != nil {
return m.GroupSeq
}
return 0
}
func (m *GenesisState) GetGroups() []*GroupInfo {
if m != nil {
return m.Groups
}
return nil
}
func (m *GenesisState) GetGroupMembers() []*GroupMember {
if m != nil {
return m.GroupMembers
}
return nil
}
func (m *GenesisState) GetGroupPolicyAccountSeq() uint64 {
if m != nil {
return m.GroupPolicyAccountSeq
}
return 0
}
func (m *GenesisState) GetGroupPolicies() []*GroupPolicyInfo {
if m != nil {
return m.GroupPolicies
}
return nil
}
func (m *GenesisState) GetProposalSeq() uint64 {
if m != nil {
return m.ProposalSeq
}
return 0
}
func (m *GenesisState) GetProposals() []*Proposal {
if m != nil {
return m.Proposals
}
return nil
}
func (m *GenesisState) GetVotes() []*Vote {
if m != nil {
return m.Votes
}
return nil
}
func init() {
proto.RegisterType((*GenesisState)(nil), "cosmos.group.v1beta1.GenesisState")
}
func init() {
proto.RegisterFile("cosmos/group/v1beta1/genesis.proto", fileDescriptor_7eedba45e0e08e2c)
}
var fileDescriptor_7eedba45e0e08e2c = []byte{
// 355 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcf, 0x4e, 0xf2, 0x40,
0x14, 0xc5, 0xe9, 0xc7, 0x9f, 0x0f, 0x06, 0x70, 0x31, 0xd1, 0x64, 0x82, 0xc9, 0x08, 0x44, 0x13,
0x36, 0xb6, 0xa2, 0x0b, 0x36, 0xc6, 0x44, 0x17, 0x12, 0x13, 0x4d, 0x48, 0x49, 0x5c, 0xb8, 0x21,
0x6d, 0x1d, 0x6b, 0x23, 0x65, 0x4a, 0xef, 0x40, 0xe4, 0x2d, 0x7c, 0x2a, 0xe3, 0x92, 0xa5, 0x4b,
0x03, 0x2f, 0x62, 0xb8, 0x53, 0x52, 0x17, 0x0d, 0x2b, 0xb8, 0x73, 0xcf, 0xef, 0x9c, 0xd3, 0xe4,
0x92, 0xb6, 0x27, 0x21, 0x94, 0x60, 0xf9, 0xb1, 0x9c, 0x45, 0xd6, 0xbc, 0xeb, 0x0a, 0xe5, 0x74,
0x2d, 0x5f, 0x4c, 0x04, 0x04, 0x60, 0x46, 0xb1, 0x54, 0x92, 0xee, 0x6b, 0x8d, 0x89, 0x1a, 0x33,
0xd1, 0x34, 0x9a, 0x99, 0xa4, 0x5a, 0x44, 0x22, 0xe1, 0xda, 0x9f, 0x79, 0x52, 0xeb, 0x6b, 0xa7,
0xa1, 0x72, 0x94, 0xa0, 0x87, 0xa4, 0x82, 0xea, 0x11, 0x88, 0x29, 0x33, 0x9a, 0x46, 0xa7, 0x60,
0x97, 0xf1, 0x61, 0x28, 0xa6, 0xb4, 0x47, 0x4a, 0xf8, 0x1f, 0xd8, 0xbf, 0x66, 0xbe, 0x53, 0x3d,
0x3f, 0x32, 0xb3, 0x62, 0xcd, 0xfe, 0x66, 0xba, 0x9b, 0xbc, 0x48, 0x3b, 0x91, 0xd3, 0x5b, 0x52,
0xd7, 0xae, 0xa1, 0x08, 0x5d, 0x11, 0x03, 0xcb, 0x23, 0xdf, 0xda, 0xc1, 0x3f, 0xa0, 0xd2, 0xae,
0xf9, 0xe9, 0x00, 0xb4, 0x47, 0x98, 0xf6, 0x89, 0xe4, 0x38, 0xf0, 0x16, 0x23, 0xc7, 0xf3, 0xe4,
0x6c, 0xa2, 0xb0, 0x6c, 0x01, 0xcb, 0x1e, 0xe0, 0x7e, 0x80, 0xeb, 0x6b, 0xbd, 0xdd, 0x34, 0xbf,
0x27, 0x7b, 0x7f, 0xc0, 0x40, 0x00, 0x2b, 0x62, 0x83, 0x93, 0x1d, 0x0d, 0xb4, 0x09, 0x7e, 0x47,
0x3d, 0x75, 0x0d, 0x04, 0xd0, 0x16, 0xa9, 0x45, 0xb1, 0x8c, 0x24, 0x38, 0x63, 0x8c, 0x2e, 0x61,
0x74, 0x75, 0xfb, 0xb6, 0x09, 0xbc, 0x24, 0x95, 0xed, 0x08, 0xec, 0x3f, 0x66, 0xf1, 0xec, 0xac,
0x41, 0x22, 0xb3, 0x53, 0x80, 0x9e, 0x91, 0xe2, 0x5c, 0x2a, 0x01, 0xac, 0x8c, 0x64, 0x23, 0x9b,
0x7c, 0x94, 0x4a, 0xd8, 0x5a, 0x78, 0x73, 0xf5, 0xb5, 0xe2, 0xc6, 0x72, 0xc5, 0x8d, 0x9f, 0x15,
0x37, 0x3e, 0xd6, 0x3c, 0xb7, 0x5c, 0xf3, 0xdc, 0xf7, 0x9a, 0xe7, 0x9e, 0x8e, 0xfd, 0x40, 0xbd,
0xce, 0x5c, 0xd3, 0x93, 0xa1, 0x95, 0xdc, 0x83, 0xfe, 0x39, 0x85, 0xe7, 0x37, 0xeb, 0x5d, 0x1f,
0x87, 0x5b, 0xc2, 0x7b, 0xb8, 0xf8, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x7b, 0xee, 0x41, 0x6d,
0x02, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Votes) > 0 {
for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x42
}
}
if len(m.Proposals) > 0 {
for iNdEx := len(m.Proposals) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Proposals[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x3a
}
}
if m.ProposalSeq != 0 {
i = encodeVarintGenesis(dAtA, i, uint64(m.ProposalSeq))
i--
dAtA[i] = 0x30
}
if len(m.GroupPolicies) > 0 {
for iNdEx := len(m.GroupPolicies) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.GroupPolicies[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x2a
}
}
if m.GroupPolicyAccountSeq != 0 {
i = encodeVarintGenesis(dAtA, i, uint64(m.GroupPolicyAccountSeq))
i--
dAtA[i] = 0x20
}
if len(m.GroupMembers) > 0 {
for iNdEx := len(m.GroupMembers) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.GroupMembers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
if len(m.Groups) > 0 {
for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
if m.GroupSeq != 0 {
i = encodeVarintGenesis(dAtA, i, uint64(m.GroupSeq))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.GroupSeq != 0 {
n += 1 + sovGenesis(uint64(m.GroupSeq))
}
if len(m.Groups) > 0 {
for _, e := range m.Groups {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if len(m.GroupMembers) > 0 {
for _, e := range m.GroupMembers {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if m.GroupPolicyAccountSeq != 0 {
n += 1 + sovGenesis(uint64(m.GroupPolicyAccountSeq))
}
if len(m.GroupPolicies) > 0 {
for _, e := range m.GroupPolicies {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if m.ProposalSeq != 0 {
n += 1 + sovGenesis(uint64(m.ProposalSeq))
}
if len(m.Proposals) > 0 {
for _, e := range m.Proposals {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
if len(m.Votes) > 0 {
for _, e := range m.Votes {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field GroupSeq", wireType)
}
m.GroupSeq = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.GroupSeq |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Groups = append(m.Groups, &GroupInfo{})
if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field GroupMembers", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.GroupMembers = append(m.GroupMembers, &GroupMember{})
if err := m.GroupMembers[len(m.GroupMembers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field GroupPolicyAccountSeq", wireType)
}
m.GroupPolicyAccountSeq = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.GroupPolicyAccountSeq |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field GroupPolicies", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.GroupPolicies = append(m.GroupPolicies, &GroupPolicyInfo{})
if err := m.GroupPolicies[len(m.GroupPolicies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProposalSeq", wireType)
}
m.ProposalSeq = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ProposalSeq |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Proposals", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Proposals = append(m.Proposals, &Proposal{})
if err := m.Proposals[len(m.Proposals)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Votes = append(m.Votes, &Vote{})
if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)

750
x/group/genesis_test.go Normal file
View File

@ -0,0 +1,750 @@
package group
import (
"testing"
"time"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/require"
)
var (
memberPub = secp256k1.GenPrivKey().PubKey()
accPub = secp256k1.GenPrivKey().PubKey()
accAddr = sdk.AccAddress(accPub.Address())
memberAddr = sdk.AccAddress(memberPub.Address())
)
func TestGenesisStateValidate(t *testing.T) {
submittedAt := time.Now().UTC()
timeout := submittedAt.Add(time.Second * 1).UTC()
groupPolicy := &GroupPolicyInfo{
Address: accAddr.String(),
GroupId: 1,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
}
err := groupPolicy.SetDecisionPolicy(&ThresholdDecisionPolicy{
Threshold: "1",
Timeout: time.Second,
})
require.NoError(t, err)
// create another group policy to set invalid decision policy for testing
groupPolicy2 := &GroupPolicyInfo{
Address: accAddr.String(),
GroupId: 1,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
}
err = groupPolicy2.SetDecisionPolicy(&ThresholdDecisionPolicy{
Threshold: "1",
Timeout: 0,
})
require.NoError(t, err)
proposal := &Proposal{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: ProposalStatusClosed,
Result: ProposalResultAccepted,
VoteState: Tally{
YesCount: "1",
NoCount: "0",
AbstainCount: "0",
VetoCount: "0",
},
Timeout: timeout,
ExecutorResult: ProposalExecutorResultSuccess,
}
err = proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{
FromAddress: accAddr.String(),
ToAddress: memberAddr.String(),
Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)},
}})
require.NoError(t, err)
testCases := []struct {
name string
genesisState GenesisState
expErr bool
}{
{
"valid genesisState",
GenesisState{
GroupSeq: 2,
Groups: []*GroupInfo{{GroupId: 1, Admin: accAddr.String(), Metadata: []byte("1"), Version: 1, TotalWeight: "1"}, {GroupId: 2, Admin: accAddr.String(), Metadata: []byte("2"), Version: 2, TotalWeight: "2"}},
GroupMembers: []*GroupMember{{GroupId: 1, Member: &Member{Address: memberAddr.String(), Weight: "1", Metadata: []byte("member metadata")}}, {GroupId: 2, Member: &Member{Address: memberAddr.String(), Weight: "2", Metadata: []byte("member metadata")}}},
GroupPolicyAccountSeq: 1,
GroupPolicies: []*GroupPolicyInfo{groupPolicy},
ProposalSeq: 1,
Proposals: []*Proposal{proposal},
Votes: []*Vote{{ProposalId: proposal.ProposalId, Voter: memberAddr.String(), SubmittedAt: submittedAt, Choice: Choice_CHOICE_YES}},
},
false,
},
{
"empty genesisState",
GenesisState{},
false,
},
{
"empty group id",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 0,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
},
true,
},
{
"invalid group admin",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: "invalid admin",
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
},
true,
},
{
"invalid group version",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 0,
TotalWeight: "1",
},
},
},
true,
},
{
"invalid group TotalWeight",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "-1",
},
},
},
true,
},
{
"invalid group policy address",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
{
Address: "invalid address",
GroupId: 1,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
},
},
},
true,
},
{
"invalid group policy admin",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
{
Address: accAddr.String(),
GroupId: 1,
Admin: "invalid admin",
Version: 1,
Metadata: []byte("policy metadata"),
},
},
},
true,
},
{
"invalid group policy's group id",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
{
Address: accAddr.String(),
GroupId: 0,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
},
},
},
true,
},
{
"invalid group policy version",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
{
Address: accAddr.String(),
GroupId: 1,
Admin: accAddr.String(),
Version: 0,
Metadata: []byte("policy metadata"),
},
},
},
true,
},
{
"invalid group policy's decision policy",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
{
Address: accAddr.String(),
GroupId: 1,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
DecisionPolicy: groupPolicy2.DecisionPolicy,
},
},
},
true,
},
{
"invalid group member's group id",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupMembers: []*GroupMember{
{
GroupId: 0,
Member: &Member{
Address: memberAddr.String(),
Weight: "1", Metadata: []byte("member metadata"),
},
},
},
},
true,
},
{
"invalid group member address",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupMembers: []*GroupMember{
{
GroupId: 1,
Member: &Member{
Address: "invalid address",
Weight: "1", Metadata: []byte("member metadata"),
},
},
},
},
true,
},
{
"invalid group member weight",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupMembers: []*GroupMember{
{
GroupId: 1,
Member: &Member{
Address: memberAddr.String(),
Weight: "-1", Metadata: []byte("member metadata"),
},
},
},
},
true,
},
{
"invalid proposal id",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 0,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
},
},
},
true,
},
{
"invalid group policy address of proposal",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: "invalid address",
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
},
},
},
true,
},
{
"invalid group version of proposal",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 0,
GroupPolicyVersion: 1,
},
},
},
true,
},
{
"invalid group policy version",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 0,
},
},
},
true,
},
{
"invalid VoteState with negative YesCount",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: ProposalStatusClosed,
Result: ProposalResultAccepted,
VoteState: Tally{
YesCount: "-1",
NoCount: "0",
AbstainCount: "0",
VetoCount: "0",
},
},
},
},
true,
},
{
"invalid VoteState with negative NoCount",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: ProposalStatusClosed,
Result: ProposalResultAccepted,
VoteState: Tally{
YesCount: "0",
NoCount: "-1",
AbstainCount: "0",
VetoCount: "0",
},
},
},
},
true,
},
{
"invalid VoteState with negative AbstainCount",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: ProposalStatusClosed,
Result: ProposalResultAccepted,
VoteState: Tally{
YesCount: "0",
NoCount: "0",
AbstainCount: "-1",
VetoCount: "0",
},
},
},
},
true,
},
{
"invalid VoteState with negative VetoCount",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: ProposalStatusClosed,
Result: ProposalResultAccepted,
VoteState: Tally{
YesCount: "0",
NoCount: "0",
AbstainCount: "0",
VetoCount: "-1",
},
},
},
},
true,
},
{
"invalid voter",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
proposal,
},
Votes: []*Vote{
{
ProposalId: proposal.ProposalId,
Voter: "invalid voter",
SubmittedAt: submittedAt,
Choice: Choice_CHOICE_YES,
},
},
},
true,
},
{
"invalid proposal id",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
proposal,
},
Votes: []*Vote{
{
ProposalId: 0,
Voter: memberAddr.String(),
SubmittedAt: submittedAt,
Choice: Choice_CHOICE_YES,
},
},
},
true,
},
{
"vote on proposal that doesn't exist",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
proposal,
},
Votes: []*Vote{
{
ProposalId: 2,
Voter: memberAddr.String(),
SubmittedAt: submittedAt,
Choice: Choice_CHOICE_YES,
},
},
},
true,
},
{
"invalid choice",
GenesisState{
Groups: []*GroupInfo{
{
GroupId: 1,
Admin: accAddr.String(),
Metadata: []byte("1"),
Version: 1,
TotalWeight: "1",
},
},
GroupPolicies: []*GroupPolicyInfo{
groupPolicy,
},
Proposals: []*Proposal{
proposal,
},
Votes: []*Vote{
{
ProposalId: proposal.ProposalId,
Voter: memberAddr.String(),
SubmittedAt: submittedAt,
Choice: Choice_CHOICE_UNSPECIFIED,
},
},
},
true,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
err := tc.genesisState.Validate()
if tc.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}

89
x/group/keeper/genesis.go Normal file
View File

@ -0,0 +1,89 @@
package keeper
import (
"encoding/json"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/group"
)
func (k Keeper) InitGenesis(ctx types.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState group.GenesisState
cdc.MustUnmarshalJSON(data, &genesisState)
if err := k.groupTable.Import(ctx.KVStore(k.key), genesisState.Groups, genesisState.GroupSeq); err != nil {
panic(errors.Wrap(err, "groups"))
}
if err := k.groupMemberTable.Import(ctx.KVStore(k.key), genesisState.GroupMembers, 0); err != nil {
panic(errors.Wrap(err, "group members"))
}
if err := k.groupPolicyTable.Import(ctx.KVStore(k.key), genesisState.GroupPolicies, 0); err != nil {
panic(errors.Wrap(err, "group policies"))
}
if err := k.groupPolicySeq.InitVal(ctx.KVStore(k.key), genesisState.GroupPolicyAccountSeq); err != nil {
panic(errors.Wrap(err, "group policy account seq"))
}
if err := k.proposalTable.Import(ctx.KVStore(k.key), genesisState.Proposals, genesisState.ProposalSeq); err != nil {
panic(errors.Wrap(err, "proposals"))
}
if err := k.voteTable.Import(ctx.KVStore(k.key), genesisState.Votes, 0); err != nil {
panic(errors.Wrap(err, "votes"))
}
return []abci.ValidatorUpdate{}
}
func (k Keeper) ExportGenesis(ctx types.Context, cdc codec.JSONCodec) *group.GenesisState {
genesisState := group.NewGenesisState()
var groups []*group.GroupInfo
groupSeq, err := k.groupTable.Export(ctx.KVStore(k.key), &groups)
if err != nil {
panic(errors.Wrap(err, "groups"))
}
genesisState.Groups = groups
genesisState.GroupSeq = groupSeq
var groupMembers []*group.GroupMember
_, err = k.groupMemberTable.Export(ctx.KVStore(k.key), &groupMembers)
if err != nil {
panic(errors.Wrap(err, "group members"))
}
genesisState.GroupMembers = groupMembers
var groupPolicies []*group.GroupPolicyInfo
_, err = k.groupPolicyTable.Export(ctx.KVStore(k.key), &groupPolicies)
if err != nil {
panic(errors.Wrap(err, "group policies"))
}
genesisState.GroupPolicies = groupPolicies
genesisState.GroupPolicyAccountSeq = k.groupPolicySeq.CurVal(ctx.KVStore(k.key))
var proposals []*group.Proposal
proposalSeq, err := k.proposalTable.Export(ctx.KVStore(k.key), &proposals)
if err != nil {
panic(errors.Wrap(err, "proposals"))
}
genesisState.Proposals = proposals
genesisState.ProposalSeq = proposalSeq
var votes []*group.Vote
_, err = k.voteTable.Export(ctx.KVStore(k.key), &votes)
if err != nil {
panic(errors.Wrap(err, "votes"))
}
genesisState.Votes = votes
return genesisState
}

View File

@ -0,0 +1,222 @@
package keeper_test
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/keeper"
)
type GenesisTestSuite struct {
suite.Suite
app *simapp.SimApp
ctx context.Context
sdkCtx sdk.Context
keeper keeper.Keeper
cdc *codec.ProtoCodec
}
func TestGenesisTestSuite(t *testing.T) {
suite.Run(t, new(GenesisTestSuite))
}
var (
memberPub = secp256k1.GenPrivKey().PubKey()
accPub = secp256k1.GenPrivKey().PubKey()
accAddr = sdk.AccAddress(accPub.Address())
memberAddr = sdk.AccAddress(memberPub.Address())
)
func (s *GenesisTestSuite) SetupSuite() {
checkTx := false
db := dbm.NewMemDB()
encCdc := simapp.MakeTestEncodingConfig()
app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{})
s.app = app
s.sdkCtx = app.BaseApp.NewUncachedContext(checkTx, tmproto.Header{})
s.keeper = app.GroupKeeper
s.cdc = codec.NewProtoCodec(app.InterfaceRegistry())
s.ctx = sdk.WrapSDKContext(s.sdkCtx)
}
func (s *GenesisTestSuite) TestInitExportGenesis() {
sdkCtx := s.sdkCtx
ctx := s.ctx
cdc := s.cdc
submittedAt := time.Now().UTC()
timeout := submittedAt.Add(time.Second * 1).UTC()
groupPolicy := &group.GroupPolicyInfo{
Address: accAddr.String(),
GroupId: 1,
Admin: accAddr.String(),
Version: 1,
Metadata: []byte("policy metadata"),
}
err := groupPolicy.SetDecisionPolicy(&group.ThresholdDecisionPolicy{
Threshold: "1",
Timeout: time.Second,
})
s.Require().NoError(err)
proposal := &group.Proposal{
ProposalId: 1,
Address: accAddr.String(),
Metadata: []byte("proposal metadata"),
GroupVersion: 1,
GroupPolicyVersion: 1,
Proposers: []string{
memberAddr.String(),
},
SubmittedAt: submittedAt,
Status: group.ProposalStatusClosed,
Result: group.ProposalResultAccepted,
VoteState: group.Tally{
YesCount: "1",
NoCount: "0",
AbstainCount: "0",
VetoCount: "0",
},
Timeout: timeout,
ExecutorResult: group.ProposalExecutorResultSuccess,
}
err = proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{
FromAddress: accAddr.String(),
ToAddress: memberAddr.String(),
Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)},
}})
s.Require().NoError(err)
genesisState := &group.GenesisState{
GroupSeq: 2,
Groups: []*group.GroupInfo{{GroupId: 1, Admin: accAddr.String(), Metadata: []byte("1"), Version: 1, TotalWeight: "1"}, {GroupId: 2, Admin: accAddr.String(), Metadata: []byte("2"), Version: 2, TotalWeight: "2"}},
GroupMembers: []*group.GroupMember{{GroupId: 1, Member: &group.Member{Address: memberAddr.String(), Weight: "1", Metadata: []byte("member metadata")}}, {GroupId: 2, Member: &group.Member{Address: memberAddr.String(), Weight: "2", Metadata: []byte("member metadata")}}},
GroupPolicyAccountSeq: 1,
GroupPolicies: []*group.GroupPolicyInfo{groupPolicy},
ProposalSeq: 1,
Proposals: []*group.Proposal{proposal},
Votes: []*group.Vote{{ProposalId: proposal.ProposalId, Voter: memberAddr.String(), SubmittedAt: submittedAt, Choice: group.Choice_CHOICE_YES}},
}
genesisBytes, err := cdc.MarshalJSON(genesisState)
s.Require().NoError(err)
genesisData := map[string]json.RawMessage{
group.ModuleName: genesisBytes,
}
s.keeper.InitGenesis(sdkCtx, cdc, genesisData[group.ModuleName])
for i, g := range genesisState.Groups {
res, err := s.keeper.GroupInfo(ctx, &group.QueryGroupInfoRequest{
GroupId: g.GroupId,
})
s.Require().NoError(err)
s.Require().Equal(g, res.Info)
membersRes, err := s.keeper.GroupMembers(ctx, &group.QueryGroupMembersRequest{
GroupId: g.GroupId,
})
s.Require().NoError(err)
s.Require().Equal(len(membersRes.Members), 1)
s.Require().Equal(membersRes.Members[0], genesisState.GroupMembers[i])
}
for _, g := range genesisState.GroupPolicies {
res, err := s.keeper.GroupPolicyInfo(ctx, &group.QueryGroupPolicyInfoRequest{
Address: g.Address,
})
s.Require().NoError(err)
s.assertGroupPoliciesEqual(g, res.Info)
}
for _, g := range genesisState.Proposals {
res, err := s.keeper.Proposal(ctx, &group.QueryProposalRequest{
ProposalId: g.ProposalId,
})
s.Require().NoError(err)
s.assertProposalsEqual(g, res.Proposal)
votesRes, err := s.keeper.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{
ProposalId: g.ProposalId,
})
s.Require().NoError(err)
s.Require().Equal(len(votesRes.Votes), 1)
s.Require().Equal(votesRes.Votes[0], genesisState.Votes[0])
}
exported := s.keeper.ExportGenesis(sdkCtx, cdc)
bz, err := cdc.MarshalJSON(exported)
s.Require().NoError(err)
var exportedGenesisState group.GenesisState
err = cdc.UnmarshalJSON(bz, &exportedGenesisState)
s.Require().NoError(err)
s.Require().Equal(genesisState.Groups, exportedGenesisState.Groups)
s.Require().Equal(genesisState.GroupMembers, exportedGenesisState.GroupMembers)
s.Require().Equal(len(genesisState.GroupPolicies), len(exportedGenesisState.GroupPolicies))
for i, g := range genesisState.GroupPolicies {
res := exportedGenesisState.GroupPolicies[i]
s.Require().NoError(err)
s.assertGroupPoliciesEqual(g, res)
}
s.Require().Equal(len(genesisState.Proposals), len(exportedGenesisState.Proposals))
for i, g := range genesisState.Proposals {
res := exportedGenesisState.Proposals[i]
s.Require().NoError(err)
s.assertProposalsEqual(g, res)
}
s.Require().Equal(genesisState.Votes, exportedGenesisState.Votes)
s.Require().Equal(genesisState.GroupSeq, exportedGenesisState.GroupSeq)
s.Require().Equal(genesisState.GroupPolicyAccountSeq, exportedGenesisState.GroupPolicyAccountSeq)
s.Require().Equal(genesisState.ProposalSeq, exportedGenesisState.ProposalSeq)
}
func (s *GenesisTestSuite) assertGroupPoliciesEqual(g *group.GroupPolicyInfo, other *group.GroupPolicyInfo) {
require := s.Require()
require.Equal(g.Address, other.Address)
require.Equal(g.GroupId, other.GroupId)
require.Equal(g.Admin, other.Admin)
require.Equal(g.Metadata, other.Metadata)
require.Equal(g.Version, other.Version)
require.Equal(g.GetDecisionPolicy(), other.GetDecisionPolicy())
}
func (s *GenesisTestSuite) assertProposalsEqual(g *group.Proposal, other *group.Proposal) {
require := s.Require()
require.Equal(g.ProposalId, other.ProposalId)
require.Equal(g.Address, other.Address)
require.Equal(g.Metadata, other.Metadata)
require.Equal(g.Proposers, other.Proposers)
require.Equal(g.SubmittedAt, other.SubmittedAt)
require.Equal(g.GroupVersion, other.GroupVersion)
require.Equal(g.GroupPolicyVersion, other.GroupPolicyVersion)
require.Equal(g.Status, other.Status)
require.Equal(g.Result, other.Result)
require.Equal(g.VoteState, other.VoteState)
require.Equal(g.Timeout, other.Timeout)
require.Equal(g.ExecutorResult, other.ExecutorResult)
require.Equal(g.GetMsgs(), other.GetMsgs())
}

View File

@ -106,14 +106,14 @@ func (q Keeper) GroupPoliciesByGroup(goCtx context.Context, request *group.Query
return nil, err
}
var accounts []*group.GroupPolicyInfo
pageRes, err := orm.Paginate(it, request.Pagination, &accounts)
var policies []*group.GroupPolicyInfo
pageRes, err := orm.Paginate(it, request.Pagination, &policies)
if err != nil {
return nil, err
}
return &group.QueryGroupPoliciesByGroupResponse{
GroupPolicies: accounts,
GroupPolicies: policies,
Pagination: pageRes,
}, nil
}
@ -133,14 +133,14 @@ func (q Keeper) GroupPoliciesByAdmin(goCtx context.Context, request *group.Query
return nil, err
}
var accounts []*group.GroupPolicyInfo
pageRes, err := orm.Paginate(it, request.Pagination, &accounts)
var policies []*group.GroupPolicyInfo
pageRes, err := orm.Paginate(it, request.Pagination, &policies)
if err != nil {
return nil, err
}
return &group.QueryGroupPoliciesByAdminResponse{
GroupPolicies: accounts,
GroupPolicies: policies,
Pagination: pageRes,
}, nil
}

View File

@ -3,6 +3,7 @@ package module
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"github.com/gorilla/mux"
@ -58,14 +59,16 @@ func (AppModuleBasic) Name() string {
// DefaultGenesis returns default genesis state as raw bytes for the group
// module.
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
// TODO: return default genesis state
return nil
return cdc.MustMarshalJSON(group.NewGenesisState())
}
// ValidateGenesis performs genesis state validation for the group module.
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.TxEncodingConfig, bz json.RawMessage) error {
// TODO: perform genesis validation
return nil
var data group.GenesisState
if err := cdc.UnmarshalJSON(bz, &data); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", group.ModuleName, err)
}
return data.Validate()
}
// GetQueryCmd returns the cli query commands for the group module
@ -127,15 +130,15 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
// InitGenesis performs genesis initialization for the group module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
// TODO: initialize genesis for group module
am.keeper.InitGenesis(ctx, cdc, data)
return []abci.ValidatorUpdate{}
}
// ExportGenesis returns the exported genesis state as raw bytes for the group
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
// TODO: export genesis for group module
return nil
gs := am.keeper.ExportGenesis(ctx, cdc)
return cdc.MustMarshalJSON(gs)
}
// RegisterServices registers a gRPC query service to respond to the

View File

@ -63,8 +63,7 @@ func (m MsgCreateGroup) ValidateBasic() error {
}
for i := range m.Members {
member := m.Members[i]
if _, err := math.NewDecFromString(member.Weight); err != nil {
// if _, err := math.ParsePositiveDecimal(member.Weight); err != nil {
if _, err := math.NewPositiveDecFromString(member.Weight); err != nil {
return sdkerrors.Wrap(err, "member weight")
}
}
@ -76,8 +75,7 @@ func (m Member) ValidateBasic() error {
if err != nil {
return sdkerrors.Wrap(err, "address")
}
if _, err := math.NewDecFromString(m.Weight); err != nil {
// if _, err := math.ParseNonNegativeDecimal(m.Weight); err != nil {
if _, err := math.NewNonNegativeDecFromString(m.Weight); err != nil {
return sdkerrors.Wrap(err, "weight")
}

View File

@ -495,18 +495,18 @@ Example:
simd tx group update-group-policy-metadata cosmos1.. cosmos1.. "AQ=="
```
#### update-group-account-policy
#### update-group-policy-decision-policy
The `update-group-account-policy` command allows users to update a group policy's decision policy.
The `update-group-policy-decision-policy` command allows users to update a group policy's decision policy.
```bash
simd tx group update-group-account-policy [admin] [group-policy-account] [decision-policy] [flags]
simd tx group update-group-policy-decision-policy [admin] [group-policy-account] [decision-policy] [flags]
```
Example:
```bash
simd tx group update-group-account-policy cosmos1.. cosmos1.. '{"@type":"/cosmos.group.v1beta1.ThresholdDecisionPolicy", "threshold":"2", "timeout":"1000s"}'
simd tx group update-group-policy-decision-policy cosmos1.. cosmos1.. '{"@type":"/cosmos.group.v1beta1.ThresholdDecisionPolicy", "threshold":"2", "timeout":"1000s"}'
```
#### create-proposal

View File

@ -17,7 +17,7 @@ This module allows the creation and management of on-chain multisig accounts and
1. **[Concepts](01_concepts.md)**
- [Group](01_concepts.md#group)
- [Group Account](01_concepts.md#group-account)
- [Group Policy](01_concepts.md#group-policy)
- [Decision Policy](01_concepts.md#decision-policy)
- [Proposal](01_concepts.md#proposal)
- [Voting](01_concepts.md#voting)
@ -25,7 +25,7 @@ This module allows the creation and management of on-chain multisig accounts and
2. **[State](02_state.md)**
- [Group Table](02_state.md#group-table)
- [Group Member Table](02_state.md#group-member-table)
- [Group Account Table](02_state.md#group-account-table)
- [Group Policy Table](02_state.md#group-policy-table)
- [Proposal](02_state.md#proposal-table)
- [Vote Table](02_state.md#vote-table)
3. **[Msg Service](03_messages.md)**
@ -33,18 +33,18 @@ This module allows the creation and management of on-chain multisig accounts and
- [Msg/UpdateGroupMembers](03_messages.md#msgupdategroupmembers)
- [Msg/UpdateGroupAdmin](03_messages.md#msgupdategroupadmin)
- [Msg/UpdateGroupMetadata](03_messages.md#msgupdategroupmetadata)
- [Msg/CreateGroupAccount](03_messages.md#msgcreategroupaccount)
- [Msg/UpdateGroupAccountAdmin](03_messages.md#msgupdategroupaccountadmin)
- [Msg/UpdateGroupAccountDecisionPolicy](03_messages.md#msgupdategroupaccountdecisionpolicy)
- [Msg/UpdateGroupAccountMetadata](03_messages.md#msgupdategroupaccountmetadata)
- [Msg/CreateGroupPolicy](03_messages.md#msgcreategrouppolicy)
- [Msg/UpdateGroupPolicyAdmin](03_messages.md#msgupdategrouppolicyadmin)
- [Msg/UpdateGroupPolicyDecisionPolicy](03_messages.md#msgupdategrouppolicydecisionpolicy)
- [Msg/UpdateGroupPolicyMetadata](03_messages.md#msgupdategrouppolicymetadata)
- [Msg/CreateProposal](03_messages.md#msgcreateproposal)
- [Msg/Vote](03_messages.md#msgvote)
- [Msg/Exec](03_messages.md#msgexec)
4. **[Events](04_events.md)**
- [EventCreateGroup](04_events.md#eventcreategroup)
- [EventUpdateGroup](04_events.md#eventupdategroup)
- [EventCreateGroupAccount](04_events.md#eventcreategroupaccount)
- [EventUpdateGroupAccount](04_events.md#eventupdategroupaccount)
- [EventCreateGroupPolicy](04_events.md#eventcreategrouppolicy)
- [EventUpdateGroupPolicy](04_events.md#eventupdategrouppolicy)
- [EventCreateProposal](04_events.md#eventcreateproposal)
- [EventVote](04_events.md#eventvote)
- [EventExec](04_events.md#eventexec)

View File

@ -167,6 +167,29 @@ func (g GroupPolicyInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error
return unpacker.UnpackAny(g.DecisionPolicy, &decisionPolicy)
}
func (g GroupInfo) PrimaryKeyFields() []interface{} {
return []interface{}{g.GroupId}
}
func (g GroupInfo) ValidateBasic() error {
if g.GroupId == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "group's GroupId")
}
_, err := sdk.AccAddressFromBech32(g.Admin)
if err != nil {
return sdkerrors.Wrap(err, "admin")
}
if _, err := math.NewNonNegativeDecFromString(g.TotalWeight); err != nil {
return sdkerrors.Wrap(err, "total weight")
}
if g.Version == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "version")
}
return nil
}
func (g GroupPolicyInfo) PrimaryKeyFields() []interface{} {
addr, err := sdk.AccAddressFromBech32(g.Address)
if err != nil {
@ -175,32 +198,34 @@ func (g GroupPolicyInfo) PrimaryKeyFields() []interface{} {
return []interface{}{addr.Bytes()}
}
func (g Proposal) PrimaryKeyFields() []interface{} {
return []interface{}{g.ProposalId}
}
func (g GroupPolicyInfo) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(g.Admin)
if err != nil {
return sdkerrors.Wrap(err, "admin")
return sdkerrors.Wrap(err, "group policy admin")
}
_, err = sdk.AccAddressFromBech32(g.Address)
if err != nil {
return sdkerrors.Wrap(err, "group policy")
return sdkerrors.Wrap(err, "group policy account address")
}
if g.GroupId == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "group")
return sdkerrors.Wrap(errors.ErrEmpty, "group policy's group id")
}
if g.Version == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "version")
return sdkerrors.Wrap(errors.ErrEmpty, "group policy version")
}
policy := g.GetDecisionPolicy()
if policy == nil {
return sdkerrors.Wrap(errors.ErrEmpty, "policy")
return sdkerrors.Wrap(errors.ErrEmpty, "group policy's decision policy")
}
if err := policy.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "policy")
return sdkerrors.Wrap(err, "group policy's decision policy")
}
return nil
}
@ -214,12 +239,46 @@ func (g GroupMember) PrimaryKeyFields() []interface{} {
func (g GroupMember) ValidateBasic() error {
if g.GroupId == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "group")
return sdkerrors.Wrap(errors.ErrEmpty, "group member's group id")
}
err := g.Member.ValidateBasic()
if err != nil {
return sdkerrors.Wrap(err, "member")
return sdkerrors.Wrap(err, "group member")
}
return nil
}
func (p Proposal) ValidateBasic() error {
if p.ProposalId == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "proposal id")
}
_, err := sdk.AccAddressFromBech32(p.Address)
if err != nil {
return sdkerrors.Wrap(err, "proposer group policy address")
}
if p.GroupVersion == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "proposal group version")
}
if p.GroupPolicyVersion == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "proposal group policy version")
}
_, err = p.VoteState.GetYesCount()
if err != nil {
return sdkerrors.Wrap(err, "proposal VoteState yes count")
}
_, err = p.VoteState.GetNoCount()
if err != nil {
return sdkerrors.Wrap(err, "proposal VoteState no count")
}
_, err = p.VoteState.GetAbstainCount()
if err != nil {
return sdkerrors.Wrap(err, "proposal VoteState abstain count")
}
_, err = p.VoteState.GetVetoCount()
if err != nil {
return sdkerrors.Wrap(err, "proposal VoteState veto count")
}
return nil
}
@ -232,6 +291,26 @@ func (v Vote) PrimaryKeyFields() []interface{} {
return []interface{}{v.ProposalId, addr.Bytes()}
}
var _ orm.Validateable = Vote{}
func (v Vote) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(v.Voter)
if err != nil {
return sdkerrors.Wrap(err, "voter")
}
if v.ProposalId == 0 {
return sdkerrors.Wrap(errors.ErrEmpty, "voter ProposalId")
}
if v.Choice == Choice_CHOICE_UNSPECIFIED {
return sdkerrors.Wrap(errors.ErrEmpty, "voter choice")
}
if _, ok := Choice_name[int32(v.Choice)]; !ok {
return sdkerrors.Wrap(errors.ErrInvalid, "choice")
}
return nil
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (q QueryGroupPoliciesByGroupResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpackGroupPolicies(unpacker, q.GroupPolicies)