feat: Add group module proto definitions and basic types (#9631)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

ref: https://github.com/cosmos/cosmos-sdk/issues/7633

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

Following up on https://github.com/cosmos/cosmos-sdk/pull/9089, this PR is the first step towards the migration of [x/group](https://github.com/regen-network/regen-ledger/tree/master/x/group) into the SDK. It introduces the group module proto definitions (types, tx, query) and other types.
The rest of the code (module, server, client, genesis...) is dependent on various other discussions (https://github.com/cosmos/cosmos-sdk/issues/9238, https://github.com/cosmos/cosmos-sdk/discussions/9182, https://github.com/cosmos/cosmos-sdk/issues/9237, https://github.com/cosmos/cosmos-sdk/issues/7773) and will be added in follow-up PRs incrementally.

---

### 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...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] 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`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [x] 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:
Marie Gauthier 2021-07-09 09:36:16 +02:00 committed by GitHub
parent d13d488d9b
commit 402148a39e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 16045 additions and 24 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
syntax = "proto3";
package cosmos.group.v1beta1;
import "cosmos/group/v1beta1/types.proto";
import "gogoproto/gogo.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/group";
// Query is the cosmos.group.v1beta1 Query service.
service Query {
// GroupInfo queries group info based on group id.
rpc GroupInfo(QueryGroupInfoRequest) returns (QueryGroupInfoResponse);
// GroupAccountInfo queries group account info based on group account address.
rpc GroupAccountInfo(QueryGroupAccountInfoRequest) returns (QueryGroupAccountInfoResponse);
// GroupMembers queries members of a group
rpc GroupMembers(QueryGroupMembersRequest) returns (QueryGroupMembersResponse);
// GroupsByAdmin queries groups by admin address.
rpc GroupsByAdmin(QueryGroupsByAdminRequest) returns (QueryGroupsByAdminResponse);
// GroupAccountsByGroup queries group accounts by group id.
rpc GroupAccountsByGroup(QueryGroupAccountsByGroupRequest) returns (QueryGroupAccountsByGroupResponse);
// GroupsByAdmin queries group accounts by admin address.
rpc GroupAccountsByAdmin(QueryGroupAccountsByAdminRequest) returns (QueryGroupAccountsByAdminResponse);
// Proposal queries a proposal based on proposal id.
rpc Proposal(QueryProposalRequest) returns (QueryProposalResponse);
// ProposalsByGroupAccount queries proposals based on group account address.
rpc ProposalsByGroupAccount(QueryProposalsByGroupAccountRequest) returns (QueryProposalsByGroupAccountResponse);
// VoteByProposalVoter queries a vote by proposal id and voter.
rpc VoteByProposalVoter(QueryVoteByProposalVoterRequest) returns (QueryVoteByProposalVoterResponse);
// VotesByProposal queries a vote by proposal.
rpc VotesByProposal(QueryVotesByProposalRequest) returns (QueryVotesByProposalResponse);
// VotesByVoter queries a vote by voter.
rpc VotesByVoter(QueryVotesByVoterRequest) returns (QueryVotesByVoterResponse);
}
// QueryGroupInfoRequest is the Query/GroupInfo request type.
message QueryGroupInfoRequest {
// group_id is the unique ID of the group.
uint64 group_id = 1;
}
// QueryGroupInfoResponse is the Query/GroupInfo response type.
message QueryGroupInfoResponse {
// info is the GroupInfo for the group.
GroupInfo info = 1;
}
// QueryGroupAccountInfoRequest is the Query/GroupAccountInfo request type.
message QueryGroupAccountInfoRequest {
// address is the account address of the group account.
string address = 1;
}
// QueryGroupAccountInfoResponse is the Query/GroupAccountInfo response type.
message QueryGroupAccountInfoResponse {
// info is the GroupAccountInfo for the group account.
GroupAccountInfo info = 1;
}
// QueryGroupMembersRequest is the Query/GroupMembersRequest request type.
message QueryGroupMembersRequest {
// group_id is the unique ID of the group.
uint64 group_id = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryGroupMembersResponse is the Query/GroupMembersResponse response type.
message QueryGroupMembersResponse {
// members are the members of the group with given group_id.
repeated GroupMember members = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryGroupsByAdminRequest is the Query/GroupsByAdminRequest request type.
message QueryGroupsByAdminRequest {
// admin is the account address of a group's admin.
string admin = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryGroupsByAdminResponse is the Query/GroupsByAdminResponse response type.
message QueryGroupsByAdminResponse {
// groups are the groups info with the provided admin.
repeated GroupInfo groups = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryGroupAccountsByGroupRequest is the Query/GroupAccountsByGroup request type.
message QueryGroupAccountsByGroupRequest {
// group_id is the unique ID of the group account's group.
uint64 group_id = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryGroupAccountsByGroupResponse is the Query/GroupAccountsByGroup response type.
message QueryGroupAccountsByGroupResponse {
// group_accounts are the group accounts info associated with the provided group.
repeated GroupAccountInfo group_accounts = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryGroupAccountsByAdminRequest is the Query/GroupAccountsByAdmin request type.
message QueryGroupAccountsByAdminRequest {
// admin is the admin address of the group account.
string admin = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryGroupAccountsByAdminResponse is the Query/GroupAccountsByAdmin response type.
message QueryGroupAccountsByAdminResponse {
// group_accounts are the group accounts info with provided admin.
repeated GroupAccountInfo group_accounts = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryProposalRequest is the Query/Proposal request type.
message QueryProposalRequest {
// proposal_id is the unique ID of a proposal.
uint64 proposal_id = 1;
}
// QueryProposalResponse is the Query/Proposal response type.
message QueryProposalResponse {
// proposal is the proposal info.
Proposal proposal = 1;
}
// QueryProposalsByGroupAccountRequest is the Query/ProposalByGroupAccount request type.
message QueryProposalsByGroupAccountRequest {
// address is the group account address related to proposals.
string address = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryProposalsByGroupAccountResponse is the Query/ProposalByGroupAccount response type.
message QueryProposalsByGroupAccountResponse {
// proposals are the proposals with given group account.
repeated Proposal proposals = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter request type.
message QueryVoteByProposalVoterRequest {
// proposal_id is the unique ID of a proposal.
uint64 proposal_id = 1;
// voter is a proposal voter account address.
string voter = 2;
}
// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter response type.
message QueryVoteByProposalVoterResponse {
// vote is the vote with given proposal_id and voter.
Vote vote = 1;
}
// QueryVotesByProposalResponse is the Query/VotesByProposal request type.
message QueryVotesByProposalRequest {
// proposal_id is the unique ID of a proposal.
uint64 proposal_id = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryVotesByProposalResponse is the Query/VotesByProposal response type.
message QueryVotesByProposalResponse {
// votes are the list of votes for given proposal_id.
repeated Vote votes = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryVotesByVoterResponse is the Query/VotesByVoter request type.
message QueryVotesByVoterRequest {
// voter is a proposal voter account address.
string voter = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryVotesByVoterResponse is the Query/VotesByVoter response type.
message QueryVotesByVoterResponse {
// votes are the list of votes by given voter.
repeated Vote votes = 1;
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

View File

@ -0,0 +1,281 @@
syntax = "proto3";
package cosmos.group.v1beta1;
option go_package = "github.com/cosmos/cosmos-sdk/x/group";
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/any.proto";
import "cosmos/group/v1beta1/types.proto";
// Msg is the cosmos.group.v1beta1 Msg service.
service Msg {
// CreateGroup creates a new group with an admin account address, a list of members and some optional metadata.
rpc CreateGroup(MsgCreateGroupRequest) returns (MsgCreateGroupResponse);
// UpdateGroupMembers updates the group members with given group id and admin address.
rpc UpdateGroupMembers(MsgUpdateGroupMembersRequest) returns (MsgUpdateGroupMembersResponse);
// UpdateGroupAdmin updates the group admin with given group id and previous admin address.
rpc UpdateGroupAdmin(MsgUpdateGroupAdminRequest) returns (MsgUpdateGroupAdminResponse);
// UpdateGroupMetadata updates the group metadata with given group id and admin address.
rpc UpdateGroupMetadata(MsgUpdateGroupMetadataRequest) returns (MsgUpdateGroupMetadataResponse);
// CreateGroupAccount creates a new group account using given DecisionPolicy.
rpc CreateGroupAccount(MsgCreateGroupAccountRequest) returns (MsgCreateGroupAccountResponse);
// UpdateGroupAccountAdmin updates a group account admin.
rpc UpdateGroupAccountAdmin(MsgUpdateGroupAccountAdminRequest) returns (MsgUpdateGroupAccountAdminResponse);
// UpdateGroupAccountDecisionPolicy allows a group account decision policy to be updated.
rpc UpdateGroupAccountDecisionPolicy(MsgUpdateGroupAccountDecisionPolicyRequest) returns (MsgUpdateGroupAccountDecisionPolicyResponse);
// UpdateGroupAccountMetadata updates a group account metadata.
rpc UpdateGroupAccountMetadata(MsgUpdateGroupAccountMetadataRequest) returns (MsgUpdateGroupAccountMetadataResponse);
// CreateProposal submits a new proposal.
rpc CreateProposal(MsgCreateProposalRequest) returns (MsgCreateProposalResponse);
// Vote allows a voter to vote on a proposal.
rpc Vote(MsgVoteRequest) returns (MsgVoteResponse);
// Exec executes a proposal.
rpc Exec(MsgExecRequest) returns (MsgExecResponse);
}
//
// Groups
//
// MsgCreateGroupRequest is the Msg/CreateGroup request type.
message MsgCreateGroupRequest {
// admin is the account address of the group admin.
string admin = 1;
// members defines the group members.
repeated Member members = 2 [(gogoproto.nullable) = false];
// metadata is any arbitrary metadata to attached to the group.
bytes metadata = 3;
}
// MsgCreateGroupResponse is the Msg/CreateGroup response type.
message MsgCreateGroupResponse {
// group_id is the unique ID of the newly created group.
uint64 group_id = 1;
}
// MsgUpdateGroupMembersRequest is the Msg/UpdateGroupMembers request type.
message MsgUpdateGroupMembersRequest {
// admin is the account address of the group admin.
string admin = 1;
// group_id is the unique ID of the group.
uint64 group_id = 2;
// member_updates is the list of members to update,
// set weight to 0 to remove a member.
repeated Member member_updates = 3 [(gogoproto.nullable) = false];
}
// MsgUpdateGroupMembersResponse is the Msg/UpdateGroupMembers response type.
message MsgUpdateGroupMembersResponse { }
// MsgUpdateGroupAdminRequest is the Msg/UpdateGroupAdmin request type.
message MsgUpdateGroupAdminRequest {
// admin is the current account address of the group admin.
string admin = 1;
// group_id is the unique ID of the group.
uint64 group_id = 2;
// new_admin is the group new admin account address.
string new_admin = 3;
}
// MsgUpdateGroupAdminResponse is the Msg/UpdateGroupAdmin response type.
message MsgUpdateGroupAdminResponse { }
// MsgUpdateGroupMetadataRequest is the Msg/UpdateGroupMetadata request type.
message MsgUpdateGroupMetadataRequest {
// admin is the account address of the group admin.
string admin = 1;
// group_id is the unique ID of the group.
uint64 group_id = 2;
// metadata is the updated group's metadata.
bytes metadata = 3;
}
// MsgUpdateGroupMetadataResponse is the Msg/UpdateGroupMetadata response type.
message MsgUpdateGroupMetadataResponse { }
//
// Group Accounts
//
// MsgCreateGroupAccountRequest is the Msg/CreateGroupAccount request type.
message MsgCreateGroupAccountRequest {
option (gogoproto.goproto_getters) = false;
// admin is the account address of the group admin.
string admin = 1;
// group_id is the unique ID of the group.
uint64 group_id = 2;
// metadata is any arbitrary metadata to attached to the group account.
bytes metadata = 3;
// decision_policy specifies the group account's decision policy.
google.protobuf.Any decision_policy = 4 [(cosmos_proto.accepts_interface) = "DecisionPolicy"];
}
// MsgCreateGroupAccountResponse is the Msg/CreateGroupAccount response type.
message MsgCreateGroupAccountResponse {
// address is the account address of the newly created group account.
string address = 1;
}
// MsgUpdateGroupAccountAdminRequest is the Msg/UpdateGroupAccountAdmin request type.
message MsgUpdateGroupAccountAdminRequest {
// admin is the account address of the group admin.
string admin = 1;
// address is the group account address.
string address = 2;
// new_admin is the new group account admin.
string new_admin = 3;
}
// MsgUpdateGroupAccountAdminResponse is the Msg/UpdateGroupAccountAdmin response type.
message MsgUpdateGroupAccountAdminResponse { }
// MsgUpdateGroupAccountDecisionPolicyRequest is the Msg/UpdateGroupAccountDecisionPolicy request type.
message MsgUpdateGroupAccountDecisionPolicyRequest {
option (gogoproto.goproto_getters) = false;
// admin is the account address of the group admin.
string admin = 1;
// address is the group account address.
string address = 2;
// decision_policy is the updated group account decision policy.
google.protobuf.Any decision_policy = 3 [(cosmos_proto.accepts_interface) = "DecisionPolicy"];
}
// MsgUpdateGroupAccountDecisionPolicyResponse is the Msg/UpdateGroupAccountDecisionPolicy response type.
message MsgUpdateGroupAccountDecisionPolicyResponse { }
// MsgUpdateGroupAccountMetadataRequest is the Msg/UpdateGroupAccountMetadata request type.
message MsgUpdateGroupAccountMetadataRequest {
// admin is the account address of the group admin.
string admin = 1;
// address is the group account address.
string address = 2;
// metadata is the updated group account metadata.
bytes metadata = 3;
}
// MsgUpdateGroupAccountMetadataResponse is the Msg/UpdateGroupAccountMetadata response type.
message MsgUpdateGroupAccountMetadataResponse { }
//
// Proposals and Voting
//
// Exec defines modes of execution of a proposal on creation or on new vote.
enum Exec {
// An empty value means that there should be a separate
// MsgExec request for the proposal to execute.
EXEC_UNSPECIFIED = 0;
// Try to execute the proposal immediately.
// If the proposal is not allowed per the DecisionPolicy,
// the proposal will still be open and could
// be executed at a later point.
EXEC_TRY = 1;
}
// MsgCreateProposalRequest is the Msg/CreateProposal request type.
message MsgCreateProposalRequest {
option (gogoproto.goproto_getters) = false;
// address is the group account address.
string address = 1;
// proposers are the account addresses of the proposers.
// Proposers signatures will be counted as yes votes.
repeated string proposers = 2;
// metadata is any arbitrary metadata to attached to the proposal.
bytes metadata = 3;
// msgs is a list of Msgs that will be executed if the proposal passes.
repeated google.protobuf.Any msgs = 4;
// exec defines the mode of execution of the proposal,
// whether it should be executed immediately on creation or not.
// If so, proposers signatures are considered as Yes votes.
Exec exec = 5;
}
// MsgCreateProposalResponse is the Msg/CreateProposal response type.
message MsgCreateProposalResponse {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
}
// MsgVoteRequest is the Msg/Vote request type.
message MsgVoteRequest {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// voter is the voter account address.
string voter = 2;
// choice is the voter's choice on the proposal.
Choice choice = 3;
// metadata is any arbitrary metadata to attached to the vote.
bytes metadata = 4;
// exec defines whether the proposal should be executed
// immediately after voting or not.
Exec exec = 5;
}
// MsgVoteResponse is the Msg/Vote response type.
message MsgVoteResponse { }
// MsgExecRequest is the Msg/Exec request type.
message MsgExecRequest {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// signer is the account address used to execute the proposal.
string signer = 2;
}
// MsgExecResponse is the Msg/Exec request type.
message MsgExecResponse { }

View File

@ -0,0 +1,272 @@
syntax = "proto3";
package cosmos.group.v1beta1;
option go_package = "github.com/cosmos/cosmos-sdk/x/group";
import "gogoproto/gogo.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/any.proto";
// Member represents a group member with an account address,
// non-zero weight and metadata.
message Member {
// address is the member's account address.
string address = 1;
// weight is the member's voting weight that should be greater than 0.
string weight = 2;
// metadata is any arbitrary metadata to attached to the member.
bytes metadata = 3;
}
// Members defines a repeated slice of Member objects.
message Members {
// members is the list of members.
repeated Member members = 1 [(gogoproto.nullable) = false];
}
// ThresholdDecisionPolicy implements the DecisionPolicy interface
message ThresholdDecisionPolicy {
option (cosmos_proto.implements_interface) = "DecisionPolicy";
// threshold is the minimum weighted sum of yes votes that must be met or exceeded for a proposal to succeed.
string threshold = 1;
// timeout is the duration from submission of a proposal to the end of voting period
// Within this times votes and exec messages can be submitted.
google.protobuf.Duration timeout = 2 [(gogoproto.stdduration) = true, (gogoproto.nullable) = false];
}
// Choice defines available types of choices for voting.
enum Choice {
// CHOICE_UNSPECIFIED defines a no-op voting choice.
CHOICE_UNSPECIFIED = 0;
// CHOICE_NO defines a no voting choice.
CHOICE_NO = 1;
// CHOICE_YES defines a yes voting choice.
CHOICE_YES = 2;
// CHOICE_ABSTAIN defines an abstaining voting choice.
CHOICE_ABSTAIN = 3;
// CHOICE_VETO defines a voting choice with veto.
CHOICE_VETO = 4;
}
//
// State
//
// GroupInfo represents the high-level on-chain information for a group.
message GroupInfo {
// group_id is the unique ID of the group.
uint64 group_id = 1;
// admin is the account address of the group's admin.
string admin = 2;
// metadata is any arbitrary metadata to attached to the group.
bytes metadata = 3;
// version is used to track changes to a group's membership structure that
// would break existing proposals. Whenever any members weight is changed,
// or any member is added or removed this version is incremented and will
// cause proposals based on older versions of this group to fail
uint64 version = 4;
// total_weight is the sum of the group members' weights.
string total_weight = 5;
}
// GroupMember represents the relationship between a group and a member.
message GroupMember {
// group_id is the unique ID of the group.
uint64 group_id = 1;
// member is the member data.
Member member = 2;
}
// GroupAccountInfo represents the high-level on-chain information for a group account.
message GroupAccountInfo {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
// address is the group account address.
string address = 1;
// group_id is the unique ID of the group.
uint64 group_id = 2;
// admin is the account address of the group admin.
string admin = 3;
// metadata is any arbitrary metadata to attached to the group account.
bytes metadata = 4;
// version is used to track changes to a group's GroupAccountInfo structure that
// would create a different result on a running proposal.
uint64 version = 5;
// decision_policy specifies the group account's decision policy.
google.protobuf.Any decision_policy = 6 [(cosmos_proto.accepts_interface) = "DecisionPolicy"];
// derivation_key is the "derivation" key of the group account,
// which is needed to derive the group root module key and execute proposals.
bytes derivation_key = 7;
}
// Proposal defines a group proposal. Any member of a group can submit a proposal
// for a group account to decide upon.
// A proposal consists of a set of `sdk.Msg`s that will be executed if the proposal
// passes as well as some optional metadata associated with the proposal.
message Proposal {
option (gogoproto.goproto_getters) = false;
// proposal_id is the unique id of the proposal.
uint64 proposal_id = 1;
// address is the group account address.
string address = 2;
// metadata is any arbitrary metadata to attached to the proposal.
bytes metadata = 3;
// proposers are the account addresses of the proposers.
repeated string proposers = 4;
// submitted_at is a timestamp specifying when a proposal was submitted.
google.protobuf.Timestamp submitted_at = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// group_version tracks the version of the group that this proposal corresponds to.
// When group membership is changed, existing proposals from previous group versions will become invalid.
uint64 group_version = 6;
// group_account_version tracks the version of the group account that this proposal corresponds to.
// When a decision policy is changed, existing proposals from previous policy versions will become invalid.
uint64 group_account_version = 7;
// Status defines proposal statuses.
enum Status {
option (gogoproto.goproto_enum_prefix) = false;
// An empty value is invalid and not allowed.
STATUS_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalStatusInvalid"];
// Initial status of a proposal when persisted.
STATUS_SUBMITTED = 1 [(gogoproto.enumvalue_customname) = "ProposalStatusSubmitted"];
// Final status of a proposal when the final tally was executed.
STATUS_CLOSED = 2 [(gogoproto.enumvalue_customname) = "ProposalStatusClosed"];
// Final status of a proposal when the group was modified before the final tally.
STATUS_ABORTED = 3 [(gogoproto.enumvalue_customname) = "ProposalStatusAborted"];
// TODO: do we want to support a withdrawn operation?
// A proposal can be deleted before the voting start time by the owner. When this happens the final status
// is Withdrawn.
// STATUS_WITHDRAWN = 4 [(gogoproto.enumvalue_customname) = "Withdrawn"];
}
// Status represents the high level position in the life cycle of the proposal. Initial value is Submitted.
Status status = 8;
// Result defines types of proposal results.
enum Result {
option (gogoproto.goproto_enum_prefix) = false;
// An empty value is invalid and not allowed
RESULT_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalResultInvalid"];
// Until a final tally has happened the status is unfinalized
RESULT_UNFINALIZED = 1 [(gogoproto.enumvalue_customname) = "ProposalResultUnfinalized"];
// Final result of the tally
RESULT_ACCEPTED = 2 [(gogoproto.enumvalue_customname) = "ProposalResultAccepted"];
// Final result of the tally
RESULT_REJECTED = 3 [(gogoproto.enumvalue_customname) = "ProposalResultRejected"];
}
// result is the final result based on the votes and election rule. Initial value is unfinalized.
// The result is persisted so that clients can always rely on this state and not have to replicate the logic.
Result result = 9;
// vote_state contains the sums of all weighted votes for this proposal.
Tally vote_state = 10 [(gogoproto.nullable) = false];
// timeout is the timestamp of the block where the proposal execution times out. Header times of the votes and execution messages
// must be before this end time to be included in the election. After the timeout timestamp the proposal can not be
// executed anymore and should be considered pending delete.
google.protobuf.Timestamp timeout = 11 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// ExecutorResult defines types of proposal executor results.
enum ExecutorResult {
option (gogoproto.goproto_enum_prefix) = false;
// An empty value is not allowed.
EXECUTOR_RESULT_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultInvalid"];
// We have not yet run the executor.
EXECUTOR_RESULT_NOT_RUN = 1 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultNotRun"];
// The executor was successful and proposed action updated state.
EXECUTOR_RESULT_SUCCESS = 2 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultSuccess"];
// The executor returned an error and proposed action didn't update state.
EXECUTOR_RESULT_FAILURE = 3 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultFailure"];
}
// executor_result is the final result based on the votes and election rule. Initial value is NotRun.
ExecutorResult executor_result = 12;
// msgs is a list of Msgs that will be executed if the proposal passes.
repeated google.protobuf.Any msgs = 13;
}
// Tally represents the sum of weighted votes.
message Tally {
option (gogoproto.goproto_getters) = false;
// yes_count is the weighted sum of yes votes.
string yes_count = 1;
// no_count is the weighted sum of no votes.
string no_count = 2;
// abstain_count is the weighted sum of abstainers
string abstain_count = 3;
// veto_count is the weighted sum of vetoes.
string veto_count = 4;
}
// Vote represents a vote for a proposal.
message Vote {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// voter is the account address of the voter.
string voter = 2;
// choice is the voter's choice on the proposal.
Choice choice = 3;
// metadata is any arbitrary metadata to attached to the vote.
bytes metadata = 4;
// submitted_at is the timestamp when the vote was submitted.
google.protobuf.Timestamp submitted_at = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}

47
types/tx/msgs.go Normal file
View File

@ -0,0 +1,47 @@
package tx
import (
fmt "fmt"
"github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// SetMsgs takes a slice of sdk.Msg's and turn them into Any's.
func SetMsgs(msgs []sdk.Msg) ([]*types.Any, error) {
anys := make([]*types.Any, len(msgs))
for i, msg := range msgs {
var err error
anys[i], err = types.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
}
return anys, nil
}
// GetMsgs takes a slice of Any's and turn them into sdk.Msg's.
func GetMsgs(anys []*types.Any, name string) ([]sdk.Msg, error) {
msgs := make([]sdk.Msg, len(anys))
for i, any := range anys {
cached := any.GetCachedValue()
if cached == nil {
return nil, fmt.Errorf("any cached value is nil, %s messages must be correctly packed any values", name)
}
msgs[i] = cached.(sdk.Msg)
}
return msgs, nil
}
// UnpackInterfaces unpacks Any's to sdk.Msg's.
func UnpackInterfaces(unpacker types.AnyUnpacker, anys []*types.Any) error {
for _, any := range anys {
var msg sdk.Msg
err := unpacker.UnpackAny(any, &msg)
if err != nil {
return err
}
}
return nil
}

View File

@ -23,13 +23,9 @@ func (t *Tx) GetMsgs() []sdk.Msg {
}
anys := t.Body.Messages
res := make([]sdk.Msg, len(anys))
for i, any := range anys {
cached := any.GetCachedValue()
if cached == nil {
panic("Any cached value is nil. Transaction messages must be correctly packed Any values.")
}
res[i] = cached.(sdk.Msg)
res, err := GetMsgs(anys, "transaction")
if err != nil {
panic(err)
}
return res
}
@ -175,15 +171,7 @@ func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
for _, any := range m.Messages {
var msg sdk.Msg
err := unpacker.UnpackAny(any, &msg)
if err != nil {
return err
}
}
return nil
return UnpackInterfaces(unpacker, m.Messages)
}
// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method

View File

@ -200,14 +200,9 @@ func (w *wrapper) GetSignaturesV2() ([]signing.SignatureV2, error) {
}
func (w *wrapper) SetMsgs(msgs ...sdk.Msg) error {
anys := make([]*codectypes.Any, len(msgs))
for i, msg := range msgs {
var err error
anys[i], err = codectypes.NewAnyWithValue(msg)
if err != nil {
return err
}
anys, err := tx.SetMsgs(msgs)
if err != nil {
return err
}
w.tx.Body.Messages = anys

16
x/group/errors.go Normal file
View File

@ -0,0 +1,16 @@
package group
import (
"github.com/cosmos/cosmos-sdk/types/errors"
)
var (
ErrEmpty = errors.Register(ModuleName, 2, "value is empty")
ErrDuplicate = errors.Register(ModuleName, 3, "duplicate value")
ErrMaxLimit = errors.Register(ModuleName, 4, "limit exceeded")
ErrType = errors.Register(ModuleName, 5, "invalid type")
ErrInvalid = errors.Register(ModuleName, 6, "invalid value")
ErrUnauthorized = errors.Register(ModuleName, 7, "unauthorized")
ErrModified = errors.Register(ModuleName, 8, "modified")
ErrExpired = errors.Register(ModuleName, 9, "expired")
)

9
x/group/keys.go Normal file
View File

@ -0,0 +1,9 @@
package group
const (
// ModuleName is the module name constant used in many places
ModuleName = "group"
// StoreKey defines the primary module store key
StoreKey = ModuleName
)

29
x/group/proposal.go Normal file
View File

@ -0,0 +1,29 @@
package group
import (
"github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
)
func (p *Proposal) GetMsgs() []sdk.Msg {
msgs, err := tx.GetMsgs(p.Msgs, "proposal")
if err != nil {
panic(err)
}
return msgs
}
func (p *Proposal) SetMsgs(msgs []sdk.Msg) error {
anys, err := tx.SetMsgs(msgs)
if err != nil {
return err
}
p.Msgs = anys
return nil
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (p Proposal) UnpackInterfaces(unpacker types.AnyUnpacker) error {
return tx.UnpackInterfaces(unpacker, p.Msgs)
}

5366
x/group/query.pb.go Normal file

File diff suppressed because it is too large Load Diff

5239
x/group/tx.pb.go Normal file

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,96 @@
package group
import (
"fmt"
"time"
proto "github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
type DecisionPolicyResult struct {
Allow bool
Final bool
}
// DecisionPolicy is the persistent set of rules to determine the result of election on a proposal.
type DecisionPolicy interface {
codec.ProtoMarshaler
ValidateBasic() error
GetTimeout() types.Duration
Allow(tally Tally, totalPower string, votingDuration time.Duration) (DecisionPolicyResult, error)
Validate(g GroupInfo) error
}
// NewGroupAccountInfo creates a new GroupAccountInfo instance
func NewGroupAccountInfo(address sdk.AccAddress, group uint64, admin sdk.AccAddress, metadata []byte,
version uint64, decisionPolicy DecisionPolicy, derivationKey []byte) (GroupAccountInfo, error) {
p := GroupAccountInfo{
Address: address.String(),
GroupId: group,
Admin: admin.String(),
Metadata: metadata,
Version: version,
DerivationKey: derivationKey,
}
err := p.SetDecisionPolicy(decisionPolicy)
if err != nil {
return GroupAccountInfo{}, err
}
return p, nil
}
func (g *GroupAccountInfo) SetDecisionPolicy(decisionPolicy DecisionPolicy) error {
msg, ok := decisionPolicy.(proto.Message)
if !ok {
return fmt.Errorf("can't proto marshal %T", msg)
}
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return err
}
g.DecisionPolicy = any
return nil
}
func (g GroupAccountInfo) GetDecisionPolicy() DecisionPolicy {
decisionPolicy, ok := g.DecisionPolicy.GetCachedValue().(DecisionPolicy)
if !ok {
return nil
}
return decisionPolicy
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (g GroupAccountInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
var decisionPolicy DecisionPolicy
return unpacker.UnpackAny(g.DecisionPolicy, &decisionPolicy)
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (q QueryGroupAccountsByGroupResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpackGroupAccounts(unpacker, q.GroupAccounts)
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (q QueryGroupAccountsByAdminResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpackGroupAccounts(unpacker, q.GroupAccounts)
}
func unpackGroupAccounts(unpacker codectypes.AnyUnpacker, accs []*GroupAccountInfo) error {
for _, g := range accs {
err := g.UnpackInterfaces(unpacker)
if err != nil {
return err
}
}
return nil
}

3379
x/group/types.pb.go Normal file

File diff suppressed because it is too large Load Diff