x/group 模块现由 Cosmos Enterprise 产品维护。如果你的应用使用了 x/group,你需要将代码迁移到 Enterprise 分发的包,并获取 Cosmos Enterprise 许可证,才能继续使用它。更多信息请参阅 Cosmos Enterprise 。
以下文档定义了 group 模块。
该模块允许创建和管理链上多签账户,并支持基于可配置的决策策略对消息执行进行投票。
组本质上是带有关联权重的一组账户的聚合。它不是一个账户,也没有余额。它本身并不具有任何形式的投票权或决策权重。它有一个“管理员”,该管理员可以向组中添加、删除和更新成员。请注意,组策略账户可以作为某个组的管理员,而且管理员不一定必须是该组的成员。
组策略
组策略是与某个组和某个决策策略关联的账户。组策略之所以从组中抽象出来,是因为一个组可能针对不同类型的操作拥有多个决策策略。将组成员管理与决策策略分开,可以使开销最小化,并保持不同策略下成员的一致性。推荐的模式是:为给定组设置一个主组策略,然后创建具有不同决策策略的独立组策略,并使用 x/authz 模块将所需权限从主账户委托给这些“子账户”。
决策策略
决策策略是组成员对提案进行投票的机制,同时也是根据计票结果决定提案是否通过的规则。
一般来说,所有决策策略都会有一个最短执行期和一个最大投票窗口。最短执行期是指提案提交后,为使其有可能被执行,必须经过的最短时间,它可以设置为 0。最大投票窗口是指提案提交后,在完成计票之前允许进行投票的最长时间。
链开发者还会定义一个应用级别的最大执行期,即在提案投票期结束后,用户被允许执行该提案的最长时间。
当前的 group 模块内置了两种决策策略:阈值和百分比。任何链开发者都可以在这两种策略基础上进行扩展,创建自定义决策策略,只要它们遵循 DecisionPolicy 接口:
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/x/group/types.go#L27-L45
阈值决策策略
阈值决策策略定义了一个赞成票阈值(基于投票人权重计票),提案必须达到该阈值才能通过。对于该决策策略,弃权和否决都会被简单视为反对票。
该决策策略还具有一个 VotingPeriod 窗口和一个 MinExecutionPeriod 窗口。前者定义了提案提交后成员可投票的时长,之后将进行计票。后者指定了提案提交后可执行提案的最短时长。如果设置为 0,则允许提案在提交时立即执行(使用 TRY_EXEC 选项)。显然,MinExecutionPeriod 不能大于 VotingPeriod+MaxExecutionPeriod(其中 MaxExecutionPeriod 是应用定义的时长,用于指定投票结束后提案仍可执行的窗口期)。
百分比决策策略
百分比决策策略与阈值决策策略类似,不同之处在于阈值不是定义为一个固定权重,而是定义为一个百分比。它更适用于组成员权重可能会更新的组,因为百分比阈值保持不变,不依赖于这些成员权重如何变化。
与阈值决策策略相同,百分比决策策略也有 VotingPeriod 和 MinExecutionPeriod 这两个参数。
组中的任何成员都可以提交提案,交由组策略账户决定。提案由一组消息组成;如果提案通过,这些消息将被执行,同时提案还可以附带任意相关元数据。
投票时有四种可选项:赞成、反对、弃权和否决。并非所有决策策略都会考虑这四种选项。投票还可以包含一些可选元数据。在当前实现中,投票窗口会在提案提交后立即开始,结束时间由组策略的决策策略定义。
撤回提案
在投票期结束之前,提案可以随时被撤回,撤回者可以是组策略的管理员,也可以是任一提案提交者。提案一旦被撤回,就会被标记为 PROPOSAL_STATUS_WITHDRAWN,并且不再允许对其进行投票或执行。
已中止提案
如果组策略在提案投票期间被更新,则该提案会被标记为 PROPOSAL_STATUS_ABORTED,并且不再允许对其进行投票或执行。这是因为组策略定义了提案投票和执行的规则,所以如果这些规则在提案生命周期中发生变化,该提案就应被标记为过时。
计票是对提案所有投票进行统计的过程。它在提案生命周期中只会发生一次,但可能由以下两个因素中的任意一个先触发:
要么有人尝试执行该提案(见下一节),这可能发生在 Msg/Exec 交易中,或者在 Exec 字段已设置的 Msg/{SubmitProposal,Vote} 交易中。当尝试执行提案时,会先进行计票,以确保提案通过。
要么在提案投票期刚结束时,于 EndBlock 触发。
如果计票结果满足决策策略的规则,则提案会被标记为 PROPOSAL_STATUS_ACCEPTED,否则会被标记为 PROPOSAL_STATUS_REJECTED。无论哪种情况,都不再允许继续投票,并且计票结果会持久化到状态中的提案 FinalTallyResult 字段里。
执行提案
只有在计票完成,且组账户的决策策略根据计票结果允许提案通过时,提案才会被执行。此类提案会被标记为 PROPOSAL_STATUS_ACCEPTED。执行必须发生在每个提案投票期结束后的 MaxExecutionPeriod 时长内(由链开发者设置)。
在当前设计中,链不会自动执行提案,而是需要用户提交 Msg/Exec 交易,依据当前投票结果和决策策略尝试执行提案。任何用户(不仅限于组成员)都可以执行已被接受的提案,执行费用由提案执行者支付。
也可以在创建提案时,或在新增投票时,通过 Msg/SubmitProposal 和 Msg/Vote 请求中的 Exec 字段尝试立即执行提案。
在前一种情况下,提案提交者的签名会被视为赞成票。
在这些情况下,如果提案无法执行(即未满足决策策略的规则),它仍会继续开放接收新投票,并可在之后再次计票和执行。
成功执行的提案,其 ExecutorResult 会被标记为 PROPOSAL_EXECUTOR_RESULT_SUCCESS。该提案会在执行后被自动清理。相反,执行失败的提案会被标记为 PROPOSAL_EXECUTOR_RESULT_FAILURE。这类提案可以重复执行多次,直到其在投票期结束后的 MaxExecutionPeriod 到期为止。
提案和投票会被自动清理,以避免状态膨胀。
投票会在以下情况下被清理:
要么在一次成功计票之后,即计票结果满足决策策略规则时,这可能由 Msg/Exec 或设置了 Exec 字段的 Msg/{SubmitProposal,Vote} 触发,
要么在提案投票期结束后立即于 EndBlock 触发。这同样适用于状态为 aborted 或 withdrawn 的提案。
取两者中先发生者。
提案会在以下情况下被清理:
在提案投票期结束且尚未计票之前,如果提案状态为 withdrawn 或 aborted,则在 EndBlock 时清理,
以及在提案成功执行后,
或者在提案的 voting_period_end + max_execution_period(定义为应用级配置)刚过去后立即于 EndBlock 触发,
取两者中先发生者。
group 模块使用 orm 包,该包提供支持主键和二级索引的表存储。orm 还定义了 Sequence,它是一个基于计数器的持久化唯一键生成器,可与 Table 一起使用。
以下是作为 group 模块一部分存储的表,以及相关的序列和索引列表。
groupTable 存储 GroupInfo:0x0 | BigEndian(GroupId) -> ProtocolBuffer(GroupInfo)。
groupSeq
在创建新组时,groupSeq 的值会递增,并对应新的 GroupId:0x1 | 0x1 -> BigEndian。
第二个 0x1 对应 ORM 的 sequenceStorageKey。
groupByAdminIndex
groupByAdminIndex 允许根据管理员地址检索组:
0x2 | len([]byte(group.Admin)) | []byte(group.Admin) | BigEndian(GroupId) -> []byte()。
组成员表
groupMemberTable 存储 GroupMember:0x10 | BigEndian(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember)。
groupMemberTable 是一张主键表,其 PrimaryKey 由 BigEndian(GroupId) | []byte(member.Address) 给出,以下索引会使用该主键。
groupMemberByGroupIndex
groupMemberByGroupIndex 允许根据组 ID 检索组成员:
0x11 | BigEndian(GroupId) | PrimaryKey -> []byte()。
groupMemberByMemberIndex
groupMemberByMemberIndex 允许根据成员地址检索组成员:
0x12 | len([]byte(member.Address)) | []byte(member.Address) | PrimaryKey -> []byte()。
组策略表
groupPolicyTable 存储 GroupPolicyInfo:0x20 | len([]byte(Address)) | []byte(Address) -> ProtocolBuffer(GroupPolicyInfo)。
groupPolicyTable 是一个主键表,它的 PrimaryKey 由
len([]byte(Address)) | []byte(Address) 给出,以下索引会使用该主键。
groupPolicySeq
创建新的组策略时,groupPolicySeq 的值会递增,并用于生成新的组策略账户 Address:
0x21 | 0x1 -> BigEndian。
第二个 0x1 对应 ORM 的 sequenceStorageKey。
groupPolicyByGroupIndex
groupPolicyByGroupIndex 支持按组 id 检索组策略:
0x22 | BigEndian(GroupId) | PrimaryKey -> []byte()。
groupPolicyByAdminIndex
groupPolicyByAdminIndex 支持按管理员地址检索组策略:
0x23 | len([]byte(Address)) | []byte(Address) | PrimaryKey -> []byte()。
提案表
proposalTable 存储 Proposal:0x30 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal)。
proposalSeq
创建新提案时,proposalSeq 的值会递增,并对应新的 ProposalId:0x31 | 0x1 -> BigEndian。
第二个 0x1 对应 ORM 的 sequenceStorageKey。
proposalByGroupPolicyIndex
proposalByGroupPolicyIndex 支持按组策略账户地址检索提案:
0x32 | len([]byte(account.Address)) | []byte(account.Address) | BigEndian(ProposalId) -> []byte()。
ProposalsByVotingPeriodEndIndex
proposalsByVotingPeriodEndIndex 支持按时间顺序的 voting_period_end 排序检索提案:
0x33 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte()。
该索引用于在投票期结束时统计提案票数,以及在 VotingPeriodEnd + MaxExecutionPeriod 时清理提案。
投票表
voteTable 存储 Vote:0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote)。
voteTable 是一个主键表,它的 PrimaryKey 由
BigEndian(ProposalId) | []byte(voter.Address) 给出,以下索引会使用该主键。
voteByProposalIndex
voteByProposalIndex 支持按提案 id 检索投票:
0x41 | BigEndian(ProposalId) | PrimaryKey -> []byte()。
voteByVoterIndex
voteByVoterIndex 支持按投票人地址检索投票:
0x42 | len([]byte(voter.Address)) | []byte(voter.Address) | PrimaryKey -> []byte()。
Msg 服务
Msg/CreateGroup
可以通过 MsgCreateGroup 创建一个新组,它包含一个管理员地址、一个成员列表,以及一些可选元数据。
元数据的最大长度由应用开发者选择,
并作为配置传入 group keeper。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L67-L80
在以下情况下,预期会失败:
元数据长度大于 MaxMetadataLen 配置
成员设置不正确(例如地址格式错误、存在重复成员,或权重为 0)。
Msg/UpdateGroupMembers
可以通过 UpdateGroupMembers 更新组成员。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L88-L102
在 MemberUpdates 列表中,可以通过将现有成员的权重设为 0 来移除该成员。
在以下情况下,预期会失败:
签名者不是该组的管理员。
对任何一个关联的组策略而言,如果其决策策略的 Validate() 方法未能通过针对更新后组的校验。
Msg/UpdateGroupAdmin
UpdateGroupAdmin 可用于更新组管理员。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L107-L120
如果签名者不是该组的管理员,预期会失败。
UpdateGroupMetadata 可用于更新组元数据。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L125-L138
在以下情况下,预期会失败:
新元数据长度大于 MaxMetadataLen 配置。
签名者不是该组的管理员。
Msg/CreateGroupPolicy
可以通过 MsgCreateGroupPolicy 创建一个新的组策略,它包含一个管理员地址、一个组 id、一个决策策略,以及一些可选元数据。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L147-L165
在以下情况下,预期会失败:
签名者不是该组的管理员。
元数据长度大于 MaxMetadataLen 配置。
决策策略的 Validate() 方法未能通过针对该组的校验。
Msg/CreateGroupWithPolicy
可以通过 MsgCreateGroupWithPolicy 创建一个带策略的新组,它包含一个管理员地址、一个成员列表、一个决策策略、一个 group_policy_as_admin 字段(可选地将组和组策略管理员设置为组策略地址),以及组和组策略的一些可选元数据。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L191-L215
其预期失败原因与 Msg/CreateGroup 和 Msg/CreateGroupPolicy 相同。
Msg/UpdateGroupPolicyAdmin
UpdateGroupPolicyAdmin 可用于更新组策略管理员。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L173-L186
如果签名者不是该组策略的管理员,预期会失败。
Msg/UpdateGroupPolicyDecisionPolicy
UpdateGroupPolicyDecisionPolicy 可用于更新决策策略。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L226-L241
在以下情况下,预期会失败:
签名者不是该组策略的管理员。
新决策策略的 Validate() 方法未能通过针对该组的校验。
UpdateGroupPolicyMetadata 可用于更新组策略元数据。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L246-L259
在以下情况下,预期会失败:
新元数据长度大于 MaxMetadataLen 配置。
签名者不是该组的管理员。
Msg/SubmitProposal
可以通过 MsgSubmitProposal 创建一个新提案,它包含一个组策略账户地址、一个提案人地址列表、一个在提案被接受时要执行的消息列表,以及一些可选元数据。
可以提供一个可选的 Exec 值,以尝试在提案创建后立即执行该提案。在这种情况下,提案人的签名会被视为赞成票。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L281-L315
在以下情况下,预期会失败:
元数据、标题或摘要长度大于 MaxMetadataLen 配置。
任意一个提案人不是组成员。
Msg/WithdrawProposal
可以使用 MsgWithdrawProposal 撤回提案,该消息包含一个 address(可以是提案人或组策略管理员)和一个 proposal_id(需要被撤回的提案)。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L323-L333
在以下情况下,预期会失败:
签名者既不是组策略管理员,也不是该提案的提案人。
提案已经关闭或中止。
Msg/Vote
可以通过 MsgVote 创建一条新投票,给定提案 id、投票人地址、一个选项(yes、no、veto 或 abstain)以及一些可选元数据。
可以提供一个可选的 Exec 值,以尝试在投票后立即执行该提案。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L338-L358
在以下情况下,预期会失败:
元数据长度大于 MaxMetadataLen 配置。
提案已不再处于投票期。
Msg/Exec
可以通过 MsgExec 执行提案。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L363-L373
在以下情况下,属于该提案的消息不会被执行:
Msg/LeaveGroup
MsgLeaveGroup 允许组成员退出一个组。
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L381-L391
在以下情况下,预期会失败:
该组成员不属于该组。
对任何一个关联的组策略而言,如果其决策策略的 Validate() 方法未能通过针对更新后组的校验。
group 模块会发出以下事件:
EventCreateGroup
类型 属性键 属性值 message action /cosmos.group.v1.Msg/CreateGroup cosmos.group.v1.EventCreateGroup group_id {groupId}
EventUpdateGroup
类型 属性键 属性值 message action /cosmos.group.v1.Msg/UpdateGroup{Admin|Metadata|Members}cosmos.group.v1.EventUpdateGroup group_id {groupId}
EventCreateGroupPolicy
类型 属性键 属性值 message action /cosmos.group.v1.Msg/CreateGroupPolicy cosmos.group.v1.EventCreateGroupPolicy address {groupPolicyAddress}
EventUpdateGroupPolicy
类型 属性键 属性值 message action /cosmos.group.v1.Msg/UpdateGroupPolicy{Admin|Metadata|DecisionPolicy}cosmos.group.v1.EventUpdateGroupPolicy address {groupPolicyAddress}
EventCreateProposal
类型 属性键 属性值 message action /cosmos.group.v1.Msg/CreateProposal cosmos.group.v1.EventCreateProposal proposal_id {proposalId}
EventWithdrawProposal
类型 属性键 属性值 message action /cosmos.group.v1.Msg/WithdrawProposal cosmos.group.v1.EventWithdrawProposal proposal_id {proposalId}
EventVote
类型 属性键 属性值 message action /cosmos.group.v1.Msg/Vote cosmos.group.v1.EventVote proposal_id {proposalId}
EventExec
类型 属性键 属性值 message action /cosmos.group.v1.Msg/Exec cosmos.group.v1.EventExec proposal_id {proposalId}cosmos.group.v1.EventExec logs {logs\_string}
EventLeaveGroup
类型 属性键 属性值 message action /cosmos.group.v1.Msg/LeaveGroup cosmos.group.v1.EventLeaveGroup proposal_id {proposalId}cosmos.group.v1.EventLeaveGroup address {address}
EventProposalPruned
类型 属性键 属性值 message action /cosmos.group.v1.Msg/LeaveGroup cosmos.group.v1.EventProposalPruned proposal_id {proposalId}cosmos.group.v1.EventProposalPruned status {ProposalStatus}cosmos.group.v1.EventProposalPruned tally_result {TallyResult}
客户端
CLI
用户可以使用 CLI 查询并与 group 模块交互。
query 命令允许用户查询 group 状态。
group-info
group-info 命令允许用户根据给定的 group id 查询组信息。
simd query group group-info [id] [flags]
示例:
simd query group group-info 1
示例输出:
admin: cosmos1..
group_id: "1"
metadata: AQ==
total_weight: "3"
version: "1"
group-policy-info
group-policy-info 命令允许用户根据 group policy 的账户地址查询组策略信息。
simd query group group-policy-info [group-policy-account] [flags]
示例:
simd query group group-policy-info cosmos1..
示例输出:
address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
See all 11 lines
group-members
group-members 命令允许用户结合分页标志根据 group id 查询组成员。
simd query group group-members [id] [flags]
示例:
simd query group group-members 1
示例输出:
members:
- group_id: "1"
member:
address: cosmos1..
metadata: AQ==
weight: "2"
- group_id: "1"
member:
address: cosmos1..
metadata: AQ==
weight: "1"
pagination:
next_key: null
total: "2"
See all 14 lines
groups-by-admin
groups-by-admin 命令允许用户结合分页标志根据管理员账户地址查询组。
simd query group groups-by-admin [admin] [flags]
示例:
simd query group groups-by-admin cosmos1..
示例输出:
groups:
- admin: cosmos1..
group_id: "1"
metadata: AQ==
total_weight: "3"
version: "1"
- admin: cosmos1..
group_id: "2"
metadata: AQ==
total_weight: "3"
version: "1"
pagination:
next_key: null
total: "2"
See all 14 lines
group-policies-by-group
group-policies-by-group 命令允许用户结合分页标志根据 group id 查询组策略。
simd query group group-policies-by-group [group-id] [flags]
示例:
simd query group group-policies-by-group 1
示例输出:
group_policies:
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
pagination:
next_key: null
total: "2"
See all 26 lines
group-policies-by-admin
group-policies-by-admin 命令允许用户结合分页标志根据管理员账户地址查询组策略。
simd query group group-policies-by-admin [admin] [flags]
示例:
simd query group group-policies-by-admin cosmos1..
示例输出:
group_policies:
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
pagination:
next_key: null
total: "2"
See all 26 lines
proposal
proposal 命令允许用户根据 id 查询提案。
simd query group proposal [id] [flags]
示例:
simd query group proposal 1
示例输出:
proposal:
address: cosmos1..
executor_result: EXECUTOR_RESULT_NOT_RUN
group_policy_version: "1"
group_version: "1"
metadata: AQ==
msgs:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "100000000"
denom: stake
from_address: cosmos1..
to_address: cosmos1..
proposal_id: "1"
proposers:
- cosmos1..
result: RESULT_UNFINALIZED
status: STATUS_SUBMITTED
submitted_at: "2021-12-17T07:06:26.310638964Z"
windows:
min_execution_period: 0s
voting_period: 432000s
vote_state:
abstain_count: "0"
no_count: "0"
veto_count: "0"
yes_count: "0"
summary: "Summary"
title: "Title"
See all 29 lines
proposals-by-group-policy
proposals-by-group-policy 命令允许用户结合分页标志根据 group policy 的账户地址查询提案。
simd query group proposals-by-group-policy [group-policy-account] [flags]
示例:
simd query group proposals-by-group-policy cosmos1..
示例输出:
pagination:
next_key: null
total: "1"
proposals:
- address: cosmos1..
executor_result: EXECUTOR_RESULT_NOT_RUN
group_policy_version: "1"
group_version: "1"
metadata: AQ==
msgs:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "100000000"
denom: stake
from_address: cosmos1..
to_address: cosmos1..
proposal_id: "1"
proposers:
- cosmos1..
result: RESULT_UNFINALIZED
status: STATUS_SUBMITTED
submitted_at: "2021-12-17T07:06:26.310638964Z"
windows:
min_execution_period: 0s
voting_period: 432000s
vote_state:
abstain_count: "0"
no_count: "0"
veto_count: "0"
yes_count: "0"
summary: "Summary"
title: "Title"
See all 32 lines
vote
vote 命令允许用户根据 proposal id 和投票者账户地址查询投票。
simd query group vote [proposal-id] [voter] [flags]
示例:
simd query group vote 1 cosmos1..
示例输出:
vote:
choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
votes-by-proposal
votes-by-proposal 命令允许用户结合分页标志根据 proposal id 查询投票。
simd query group votes-by-proposal [proposal-id] [flags]
示例:
simd query group votes-by-proposal 1
示例输出:
pagination:
next_key: null
total: "1"
votes:
- choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
votes-by-voter
votes-by-voter 命令允许用户结合分页标志根据投票者账户地址查询投票。
simd query group votes-by-voter [voter] [flags]
示例:
simd query group votes-by-voter cosmos1..
示例输出:
pagination:
next_key: null
total: "1"
votes:
- choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
tx 命令允许用户与 group 模块交互。
create-group
create-group 命令允许用户创建一个组,该组是带有关联权重的成员账户以及一个管理员账户的聚合。
simd tx group create-group [admin] [metadata] [members-json-file]
示例:
simd tx group create-group cosmos1.. "AQ==" members.json
update-group-admin
update-group-admin 命令允许用户更新组的管理员。
simd tx group update-group-admin [admin] [group-id] [new-admin] [flags]
示例:
simd tx group update-group-admin cosmos1.. 1 cosmos1..
update-group-members
update-group-members 命令允许用户更新组成员。
simd tx group update-group-members [admin] [group-id] [members-json-file] [flags]
示例:
simd tx group update-group-members cosmos1.. 1 members.json
update-group-metadata 命令允许用户更新组的元数据。
simd tx group update-group-metadata [admin] [group-id] [metadata] [flags]
示例:
simd tx group update-group-metadata cosmos1.. 1 "AQ=="
create-group-policy
create-group-policy 命令允许用户创建组策略,组策略是一个与组和决策策略关联的账户。
simd tx group create-group-policy [admin] [group-id] [metadata] [decision-policy] [flags]
示例:
simd tx group create-group-policy cosmos1.. 1 "AQ==" '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
create-group-with-policy
create-group-with-policy 命令允许用户创建一个组,该组是带有关联权重的成员账户以及一个带决策策略的管理员账户的聚合。如果将 --group-policy-as-admin 标志设置为 true,group policy 地址将成为该组和 group policy 的管理员。
simd tx group create-group-with-policy [admin] [group-metadata] [group-policy-metadata] [members-json-file] [decision-policy] [flags]
示例:
simd tx group create-group-with-policy cosmos1.. "AQ==" "AQ==" members.json '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
update-group-policy-admin
update-group-policy-admin 命令允许用户更新 group policy 管理员。
simd tx group update-group-policy-admin [admin] [group-policy-account] [new-admin] [flags]
示例:
simd tx group update-group-policy-admin cosmos1.. cosmos1.. cosmos1..
update-group-policy-metadata 命令允许用户更新 group policy 元数据。
simd tx group update-group-policy-metadata [admin] [group-policy-account] [new-metadata] [flags]
示例:
simd tx group update-group-policy-metadata cosmos1.. cosmos1.. "AQ=="
update-group-policy-decision-policy
update-group-policy-decision-policy 命令允许用户更新组策略的决策策略。
simd tx group update-group-policy-decision-policy [admin] [group-policy-account] [decision-policy] [flags]
示例:
simd tx group update-group-policy-decision-policy cosmos1.. cosmos1.. '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"2", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
submit-proposal
submit-proposal 命令允许用户提交新提案。
simd tx group submit-proposal [group-policy-account] [proposer[,proposer] * ] [msg_tx_json_file] [metadata] [flags]
示例:
simd tx group submit-proposal cosmos1.. cosmos1.. msg_tx.json "AQ=="
withdraw-proposal
withdraw-proposal 命令允许用户撤回提案。
simd tx group withdraw-proposal [proposal-id] [group-policy-admin-or-proposer]
示例:
simd tx group withdraw-proposal 1 cosmos1..
vote
vote 命令允许用户对提案进行投票。
simd tx group vote proposal-id] [voter] [choice] [metadata] [flags]
示例:
simd tx group vote 1 cosmos1.. CHOICE_YES "AQ=="
exec
exec 命令允许用户执行提案。
simd tx group exec [proposal-id] [flags]
示例:
leave-group
leave-group 命令允许组成员离开该组。
simd tx group leave-group [member-address] [group-id]
示例:
simd tx group leave-group cosmos1... 1
gRPC
用户可以使用 gRPC 端点查询 group 模块。
GroupInfo
GroupInfo 端点允许用户通过给定的组 ID 查询组信息。
cosmos.group.v1.Query/GroupInfo
示例:
grpcurl -plaintext \
-d '{"group_id":1}' localhost:9090 cosmos.group.v1.Query/GroupInfo
示例输出:
{
"info" : {
"groupId" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
}
}
GroupPolicyInfo
GroupPolicyInfo 端点允许用户通过组策略的账户地址查询组策略信息。
cosmos.group.v1.Query/GroupPolicyInfo
示例:
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPolicyInfo
示例输出:
{
"info" : {
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows": {"voting_period": "120h", "min_execution_period": "0s"}},
}
}
GroupMembers
GroupMembers 端点允许用户通过组 ID 并结合分页标志查询组成员。
cosmos.group.v1.Query/GroupMembers
示例:
grpcurl -plaintext \
-d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupMembers
示例输出:
{
"members" : [
{
"groupId" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "1"
}
},
{
"groupId" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "2"
}
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupsByAdmin
GroupsByAdmin 端点允许用户通过管理员账户地址并结合分页标志查询组。
cosmos.group.v1.Query/GroupsByAdmin
示例:
grpcurl -plaintext \
-d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupsByAdmin
示例输出:
{
"groups" : [
{
"groupId" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
},
{
"groupId" : "2",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupPoliciesByGroup
GroupPoliciesByGroup 端点允许用户通过组 ID 并结合分页标志查询组策略。
cosmos.group.v1.Query/GroupPoliciesByGroup
示例:
grpcurl -plaintext \
-d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByGroup
示例输出:
{
"GroupPolicies" : [
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
},
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupPoliciesByAdmin
GroupPoliciesByAdmin 端点允许用户通过管理员账户地址并结合分页标志查询组策略。
cosmos.group.v1.Query/GroupPoliciesByAdmin
示例:
grpcurl -plaintext \
-d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByAdmin
示例输出:
{
"GroupPolicies" : [
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
},
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
Proposal
Proposal 端点允许用户通过 ID 查询提案。
cosmos.group.v1.Query/Proposal
示例:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/Proposal
示例输出:
{
"proposal" : {
"proposalId" : "1",
"address" : "cosmos1..",
"proposers" : [
"cosmos1.."
],
"submittedAt" : "2021-12-17T07:06:26.310638964Z",
"groupVersion" : "1",
"GroupPolicyVersion" : "1",
"status" : "STATUS_SUBMITTED",
"result" : "RESULT_UNFINALIZED",
"voteState" : {
"yesCount" : "0",
"noCount" : "0",
"abstainCount" : "0",
"vetoCount" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executorResult" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{ "@type" : "/cosmos.bank.v1beta1.MsgSend" , "amount" : [{ " denom ":" stake "," amount ":" 100000000 "}]," fromAddress ":" cosmos1.. "," toAddress ":" cosmos1.. "}
],
" title ": " Title ",
" summary ": " Summary ",
}
}
See all 30 lines
ProposalsByGroupPolicy
ProposalsByGroupPolicy 端点允许用户通过组策略的账户地址并结合分页标志查询提案。
cosmos.group.v1.Query/ProposalsByGroupPolicy
示例:
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/ProposalsByGroupPolicy
示例输出:
{
"proposals" : [
{
"proposalId" : "1",
"address" : "cosmos1..",
"proposers" : [
"cosmos1.."
],
"submittedAt" : "2021-12-17T08:03:27.099649352Z",
"groupVersion" : "1",
"GroupPolicyVersion" : "1",
"status" : "STATUS_CLOSED",
"result" : "RESULT_ACCEPTED",
"voteState" : {
"yesCount" : "1",
"noCount" : "0",
"abstainCount" : "0",
"vetoCount" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executorResult" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{ "@type" : "/cosmos.bank.v1beta1.MsgSend" , "amount" : [{ " denom ":" stake "," amount ":" 100000000 "}]," fromAddress ":" cosmos1.. "," toAddress ":" cosmos1.. "}
],
" title ": " Title ",
" summary ": " Summary ",
}
],
" pagination ": {
" total ": " 1 "
}
}
See all 35 lines
VoteByProposalVoter
VoteByProposalVoter 端点允许用户通过提案 ID 和投票人账户地址查询投票。
cosmos.group.v1.Query/VoteByProposalVoter
示例:
grpcurl -plaintext \
-d '{"proposal_id":"1","voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VoteByProposalVoter
示例输出:
{
"vote" : {
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
}
VotesByProposal
VotesByProposal 端点允许用户通过提案 ID 并结合分页标志查询投票。
cosmos.group.v1.Query/VotesByProposal
示例:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/VotesByProposal
示例输出:
{
"votes" : [
{
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"total" : "1"
}
}
See all 13 lines
VotesByVoter
VotesByVoter 端点允许用户通过投票人账户地址并结合分页标志查询投票。
cosmos.group.v1.Query/VotesByVoter
示例:
grpcurl -plaintext \
-d '{"voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VotesByVoter
示例输出:
{
"votes" : [
{
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"total" : "1"
}
}
See all 13 lines
REST
用户可以使用 REST 端点查询 group 模块。
GroupInfo
GroupInfo 端点允许用户通过给定的组 ID 查询组信息。
/cosmos/group/v1/group_info/ {group_id}
示例:
curl localhost:1317/cosmos/group/v1/group_info/1
示例输出:
{
"info" : {
"id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
}
}
GroupPolicyInfo
GroupPolicyInfo 端点允许用户通过组策略的账户地址查询组策略信息。
/cosmos/group/v1/group_policy_info/ {address}
示例:
curl localhost:1317/cosmos/group/v1/group_policy_info/cosmos1..
示例输出:
{
"info" : {
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
}
See all 17 lines
GroupMembers
GroupMembers 端点允许用户通过组 ID 并结合分页标志查询组成员。
/cosmos/group/v1/group_members/ {group_id}
示例:
curl localhost:1317/cosmos/group/v1/group_members/1
示例输出:
{
"members" : [
{
"group_id" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "1",
"metadata" : "AQ=="
}
},
{
"group_id" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "2",
"metadata" : "AQ=="
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 23 lines
GroupsByAdmin
GroupsByAdmin 端点允许用户按管理员账户地址查询组,并支持分页参数。
/cosmos/group/v1/groups_by_admin/ {admin}
示例:
curl localhost:1317/cosmos/group/v1/groups_by_admin/cosmos1..
示例输出:
{
"groups" : [
{
"id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
},
{
"id" : "2",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 22 lines
GroupPoliciesByGroup
GroupPoliciesByGroup 端点允许用户按组 ID 查询组策略,并支持分页参数。
/cosmos/group/v1/group_policies_by_group/ {group_id}
示例:
curl localhost:1317/cosmos/group/v1/group_policies_by_group/1
示例输出:
{
"group_policies" : [
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
},
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 38 lines
GroupPoliciesByAdmin
GroupPoliciesByAdmin 端点允许用户按管理员账户地址查询组策略,并支持分页参数。
/cosmos/group/v1/group_policies_by_admin/ {admin}
示例:
curl localhost:1317/cosmos/group/v1/group_policies_by_admin/cosmos1..
示例输出:
{
"group_policies" : [
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
},
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
See all 37 lines
Proposal
Proposal 端点允许用户按 ID 查询提案。
/cosmos/group/v1/proposal/ {proposal_id}
示例:
curl localhost:1317/cosmos/group/v1/proposal/1
示例输出:
{
"proposal" : {
"proposal_id" : "1",
"address" : "cosmos1..",
"metadata" : "AQ==",
"proposers" : [
"cosmos1.."
],
"submitted_at" : "2021-12-17T07:06:26.310638964Z",
"group_version" : "1",
"group_policy_version" : "1",
"status" : "STATUS_SUBMITTED",
"result" : "RESULT_UNFINALIZED",
"vote_state" : {
"yes_count" : "0",
"no_count" : "0",
"abstain_count" : "0",
"veto_count" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executor_result" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{
"@type" : "/cosmos.bank.v1beta1.MsgSend",
"from_address" : "cosmos1..",
"to_address" : "cosmos1..",
"amount" : [
{
"denom" : "stake",
"amount" : "100000000"
}
]
}
],
"title" : "Title",
"summary" : "Summary",
}
}
See all 41 lines
ProposalsByGroupPolicy
ProposalsByGroupPolicy 端点允许用户按组策略的账户地址查询提案,并支持分页参数。
/cosmos/group/v1/proposals_by_group_policy/ {address}
示例:
curl localhost:1317/cosmos/group/v1/proposals_by_group_policy/cosmos1..
示例输出:
{
"proposals" : [
{
"id" : "1",
"group_policy_address" : "cosmos1..",
"metadata" : "AQ==",
"proposers" : [
"cosmos1.."
],
"submit_time" : "2021-12-17T08:03:27.099649352Z",
"group_version" : "1",
"group_policy_version" : "1",
"status" : "STATUS_CLOSED",
"result" : "RESULT_ACCEPTED",
"vote_state" : {
"yes_count" : "1",
"no_count" : "0",
"abstain_count" : "0",
"veto_count" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executor_result" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{
"@type" : "/cosmos.bank.v1beta1.MsgSend",
"from_address" : "cosmos1..",
"to_address" : "cosmos1..",
"amount" : [
{
"denom" : "stake",
"amount" : "100000000"
}
]
}
]
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 45 lines
VoteByProposalVoter
VoteByProposalVoter 端点允许用户按提案 ID 和投票人账户地址查询投票。
/cosmos/group/v1/vote_by_proposal_voter/ {proposal_id} / {voter}
示例:
curl localhost:1317/cosmos/group/v1beta1/vote_by_proposal_voter/1/cosmos1..
示例输出:
{
"vote" : {
"proposal_id" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"metadata" : "AQ==",
"submitted_at" : "2021-12-17T08:05:02.490164009Z"
}
}
VotesByProposal
VotesByProposal 端点允许用户按提案 ID 查询投票,并支持分页参数。
/cosmos/group/v1/votes_by_proposal/ {proposal_id}
示例:
curl localhost:1317/cosmos/group/v1/votes_by_proposal/1
示例输出:
{
"votes" : [
{
"proposal_id" : "1",
"voter" : "cosmos1..",
"option" : "CHOICE_YES",
"metadata" : "AQ==",
"submit_time" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 15 lines
VotesByVoter
VotesByVoter 端点允许用户按投票人账户地址查询投票,并支持分页参数。
/cosmos/group/v1/votes_by_voter/ {voter}
示例:
curl localhost:1317/cosmos/group/v1/votes_by_voter/cosmos1..
示例输出:
{
"votes" : [
{
"proposal_id" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"metadata" : "AQ==",
"submitted_at" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 15 lines
元数据
组模块提供了四个可放置元数据的位置,用户可以在这些位置为其执行的链上操作补充更多上下文。默认情况下,所有元数据字段的长度上限均为 255 个字符,元数据可根据所需数据量以 JSON 格式存储在链上或链下。这里我们给出了 JSON 结构及数据存储位置的建议。在提出这些建议时,有两个重要因素。第一,组模块和治理模块应彼此保持一致,需要注意的是,所有组创建的提案数量可能相当大。第二,区块浏览器和治理界面等客户端应用应能够对跨链元数据结构的一致性保持信心。
Proposal
位置:链下,以存储在 IPFS 上的 JSON 对象形式保存(与 gov proposal 保持一致)
{
"title" : "" ,
"authors" : [ "" ],
"summary" : "" ,
"details" : "" ,
"proposal_forum_url" : "" ,
"vote_option_context" : "" ,
}
authors 字段是字符串数组,这样可以在元数据中列出多个作者。
在 v0.46 中,authors 字段是逗号分隔的字符串。为保证向后兼容,建议前端同时支持这两种格式。
Vote
位置:链上,以 JSON 形式存储,且需满足 255 字符限制(与 gov vote 保持一致)
Group
位置:链下,以存储在 IPFS 上的 JSON 对象形式保存
{
"name" : "" ,
"description" : "" ,
"group_website_url" : "" ,
"group_forum_url" : "" ,
}
Decision policy
位置:链上,以 JSON 形式存储,且需满足 255 字符限制
{
"name" : "" ,
"description" : "" ,
}
The x/group module is now maintained under the Cosmos Enterprise offering. If your application uses x/group, you will need to migrate your code to the Enterprise-distributed package and obtain a Cosmos Enterprise license to continue using it. Please see Cosmos Enterprise to learn more.
Abstract
The following documents specify the group module.
This module allows the creation and management of on-chain multisig accounts and enables voting for message execution based on configurable decision policies.
Contents
Concepts
Group
A group is simply an aggregation of accounts with associated weights. It is not
an account and doesn’t have a balance. It doesn’t in and of itself have any
sort of voting or decision weight. It does have an “administrator” which has
the ability to add, remove and update members in the group. Note that a
group policy account could be an administrator of a group, and that the
administrator doesn’t necessarily have to be a member of the group.
Group Policy
A group policy is an account associated with a group and a decision policy.
Group policies are abstracted from groups because a single group may have
multiple decision policies for different types of actions. Managing group
membership separately from decision policies results in the least overhead
and keeps membership consistent across different policies. The pattern that
is recommended is to have a single master group policy for a given group,
and then to create separate group policies with different decision policies
and delegate the desired permissions from the master account to
those “sub-accounts” using the x/authz module.
Decision Policy
A decision policy is the mechanism by which members of a group can vote on
proposals, as well as the rules that dictate whether a proposal should pass
or not based on its tally outcome.
All decision policies generally would have a mininum execution period and a
maximum voting window. The minimum execution period is the minimum amount of time
that must pass after submission in order for a proposal to potentially be executed, and it may
be set to 0. The maximum voting window is the maximum time after submission that a proposal may
be voted on before it is tallied.
The chain developer also defines an app-wide maximum execution period, which is
the maximum amount of time after a proposal’s voting period end where users are
allowed to execute a proposal.
The current group module comes shipped with two decision policies: threshold
and percentage. Any chain developer can extend upon these two, by creating
custom decision policies, as long as they adhere to the DecisionPolicy
interface:
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/x/group/types.go#L27-L45
Threshold decision policy
A threshold decision policy defines a threshold of yes votes (based on a tally
of voter weights) that must be achieved in order for a proposal to pass. For
this decision policy, abstain and veto are simply treated as no’s.
This decision policy also has a VotingPeriod window and a MinExecutionPeriod
window. The former defines the duration after proposal submission where members
are allowed to vote, after which tallying is performed. The latter specifies
the minimum duration after proposal submission where the proposal can be
executed. If set to 0, then the proposal is allowed to be executed immediately
on submission (using the TRY_EXEC option). Obviously, MinExecutionPeriod
cannot be greater than VotingPeriod+MaxExecutionPeriod (where MaxExecution is
the app-defined duration that specifies the window after voting ended where a
proposal can be executed).
Percentage decision policy
A percentage decision policy is similar to a threshold decision policy, except
that the threshold is not defined as a constant weight, but as a percentage.
It’s more suited for groups where the group members’ weights can be updated, as
the percentage threshold stays the same, and doesn’t depend on how those member
weights get updated.
Same as the Threshold decision policy, the percentage decision policy has the
two VotingPeriod and MinExecutionPeriod parameters.
Proposal
Any member(s) of a group can submit a proposal for a group policy account to decide upon.
A proposal consists of a set of messages that will be executed if the proposal
passes as well as any metadata associated with the proposal.
Voting
There are four choices to choose while voting - yes, no, abstain and veto. Not
all decision policies will take the four choices into account. Votes can contain some optional metadata.
In the current implementation, the voting window begins as soon as a proposal
is submitted, and the end is defined by the group policy’s decision policy.
Withdrawing Proposals
Proposals can be withdrawn any time before the voting period end, either by the
admin of the group policy or by one of the proposers. Once withdrawn, it is
marked as PROPOSAL_STATUS_WITHDRAWN, and no more voting or execution is
allowed on it.
Aborted Proposals
If the group policy is updated during the voting period of the proposal, then
the proposal is marked as PROPOSAL_STATUS_ABORTED, and no more voting or
execution is allowed on it. This is because the group policy defines the rules
of proposal voting and execution, so if those rules change during the lifecycle
of a proposal, then the proposal should be marked as stale.
Tallying
Tallying is the counting of all votes on a proposal. It happens only once in
the lifecycle of a proposal, but can be triggered by two factors, whichever
happens first:
either someone tries to execute the proposal (see next section), which can
happen on a Msg/Exec transaction, or a Msg/{SubmitProposal,Vote}
transaction with the Exec field set. When a proposal execution is attempted,
a tally is done first to make sure the proposal passes.
or on EndBlock when the proposal’s voting period end just passed.
If the tally result passes the decision policy’s rules, then the proposal is
marked as PROPOSAL_STATUS_ACCEPTED, or else it is marked as
PROPOSAL_STATUS_REJECTED. In any case, no more voting is allowed anymore, and the tally
result is persisted to state in the proposal’s FinalTallyResult.
Executing Proposals
Proposals are executed only when the tallying is done, and the group account’s
decision policy allows the proposal to pass based on the tally outcome. They
are marked by the status PROPOSAL_STATUS_ACCEPTED. Execution must happen
before a duration of MaxExecutionPeriod (set by the chain developer) after
each proposal’s voting period end.
Proposals will not be automatically executed by the chain in this current design,
but rather a user must submit a Msg/Exec transaction to attempt to execute the
proposal based on the current votes and decision policy. Any user (not only the
group members) can execute proposals that have been accepted, and execution fees are
paid by the proposal executor.
It’s also possible to try to execute a proposal immediately on creation or on
new votes using the Exec field of Msg/SubmitProposal and Msg/Vote requests.
In the former case, proposers signatures are considered as yes votes.
In these cases, if the proposal can’t be executed (i.e. it didn’t pass the
decision policy’s rules), it will still be opened for new votes and
could be tallied and executed later on.
A successful proposal execution will have its ExecutorResult marked as
PROPOSAL_EXECUTOR_RESULT_SUCCESS. The proposal will be automatically pruned
after execution. On the other hand, a failed proposal execution will be marked
as PROPOSAL_EXECUTOR_RESULT_FAILURE. Such a proposal can be re-executed
multiple times, until it expires after MaxExecutionPeriod after voting period
end.
Pruning
Proposals and votes are automatically pruned to avoid state bloat.
Votes are pruned:
either after a successful tally, i.e. a tally whose result passes the decision
policy’s rules, which can be trigged by a Msg/Exec or a
Msg/{SubmitProposal,Vote} with the Exec field set,
or on EndBlock right after the proposal’s voting period end. This applies to proposals with status aborted or withdrawn too.
whichever happens first.
Proposals are pruned:
on EndBlock whose proposal status is withdrawn or aborted on proposal’s voting period end before tallying,
and either after a successful proposal execution,
or on EndBlock right after the proposal’s voting_period_end +
max_execution_period (defined as an app-wide configuration) is passed,
whichever happens first.
State
The group module uses the orm package which provides table storage with support for
primary keys and secondary indexes. orm also defines Sequence which is a persistent unique key generator based on a counter that can be used along with Tables.
Here’s the list of tables and associated sequences and indexes stored as part of the group module.
Group Table
The groupTable stores GroupInfo: 0x0 | BigEndian(GroupId) -> ProtocolBuffer(GroupInfo).
groupSeq
The value of groupSeq is incremented when creating a new group and corresponds to the new GroupId: 0x1 | 0x1 -> BigEndian.
The second 0x1 corresponds to the ORM sequenceStorageKey.
groupByAdminIndex
groupByAdminIndex allows to retrieve groups by admin address:
0x2 | len([]byte(group.Admin)) | []byte(group.Admin) | BigEndian(GroupId) -> []byte().
Group Member Table
The groupMemberTable stores GroupMembers: 0x10 | BigEndian(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember).
The groupMemberTable is a primary key table and its PrimaryKey is given by
BigEndian(GroupId) | []byte(member.Address) which is used by the following indexes.
groupMemberByGroupIndex
groupMemberByGroupIndex allows to retrieve group members by group id:
0x11 | BigEndian(GroupId) | PrimaryKey -> []byte().
groupMemberByMemberIndex
groupMemberByMemberIndex allows to retrieve group members by member address:
0x12 | len([]byte(member.Address)) | []byte(member.Address) | PrimaryKey -> []byte().
Group Policy Table
The groupPolicyTable stores GroupPolicyInfo: 0x20 | len([]byte(Address)) | []byte(Address) -> ProtocolBuffer(GroupPolicyInfo).
The groupPolicyTable is a primary key table and its PrimaryKey is given by
len([]byte(Address)) | []byte(Address) which is used by the following indexes.
groupPolicySeq
The value of groupPolicySeq is incremented when creating a new group policy and is used to generate the new group policy account Address:
0x21 | 0x1 -> BigEndian.
The second 0x1 corresponds to the ORM sequenceStorageKey.
groupPolicyByGroupIndex
groupPolicyByGroupIndex allows to retrieve group policies by group id:
0x22 | BigEndian(GroupId) | PrimaryKey -> []byte().
groupPolicyByAdminIndex
groupPolicyByAdminIndex allows to retrieve group policies by admin address:
0x23 | len([]byte(Address)) | []byte(Address) | PrimaryKey -> []byte().
Proposal Table
The proposalTable stores Proposals: 0x30 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal).
proposalSeq
The value of proposalSeq is incremented when creating a new proposal and corresponds to the new ProposalId: 0x31 | 0x1 -> BigEndian.
The second 0x1 corresponds to the ORM sequenceStorageKey.
proposalByGroupPolicyIndex
proposalByGroupPolicyIndex allows to retrieve proposals by group policy account address:
0x32 | len([]byte(account.Address)) | []byte(account.Address) | BigEndian(ProposalId) -> []byte().
ProposalsByVotingPeriodEndIndex
proposalsByVotingPeriodEndIndex allows to retrieve proposals sorted by chronological voting_period_end:
0x33 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte().
This index is used when tallying the proposal votes at the end of the voting period, and for pruning proposals at VotingPeriodEnd + MaxExecutionPeriod.
Vote Table
The voteTable stores Votes: 0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote).
The voteTable is a primary key table and its PrimaryKey is given by
BigEndian(ProposalId) | []byte(voter.Address) which is used by the following indexes.
voteByProposalIndex
voteByProposalIndex allows to retrieve votes by proposal id:
0x41 | BigEndian(ProposalId) | PrimaryKey -> []byte().
voteByVoterIndex
voteByVoterIndex allows to retrieve votes by voter address:
0x42 | len([]byte(voter.Address)) | []byte(voter.Address) | PrimaryKey -> []byte().
Msg Service
Msg/CreateGroup
A new group can be created with the MsgCreateGroup, which has an admin address, a list of members and some optional metadata.
The metadata has a maximum length that is chosen by the app developer, and
passed into the group keeper as a config.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L67-L80
It’s expected to fail if
metadata length is greater than MaxMetadataLen config
members are not correctly set (e.g. wrong address format, duplicates, or with 0 weight).
Msg/UpdateGroupMembers
Group members can be updated with the UpdateGroupMembers.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L88-L102
In the list of MemberUpdates, an existing member can be removed by setting its weight to 0.
It’s expected to fail if:
the signer is not the admin of the group.
for any one of the associated group policies, if its decision policy’s Validate() method fails against the updated group.
Msg/UpdateGroupAdmin
The UpdateGroupAdmin can be used to update a group admin.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L107-L120
It’s expected to fail if the signer is not the admin of the group.
The UpdateGroupMetadata can be used to update a group metadata.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L125-L138
It’s expected to fail if:
new metadata length is greater than MaxMetadataLen config.
the signer is not the admin of the group.
Msg/CreateGroupPolicy
A new group policy can be created with the MsgCreateGroupPolicy, which has an admin address, a group id, a decision policy and some optional metadata.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L147-L165
It’s expected to fail if:
the signer is not the admin of the group.
metadata length is greater than MaxMetadataLen config.
the decision policy’s Validate() method doesn’t pass against the group.
Msg/CreateGroupWithPolicy
A new group with policy can be created with the MsgCreateGroupWithPolicy, which has an admin address, a list of members, a decision policy, a group_policy_as_admin field to optionally set group and group policy admin with group policy address and some optional metadata for group and group policy.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L191-L215
It’s expected to fail for the same reasons as Msg/CreateGroup and Msg/CreateGroupPolicy.
Msg/UpdateGroupPolicyAdmin
The UpdateGroupPolicyAdmin can be used to update a group policy admin.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L173-L186
It’s expected to fail if the signer is not the admin of the group policy.
Msg/UpdateGroupPolicyDecisionPolicy
The UpdateGroupPolicyDecisionPolicy can be used to update a decision policy.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L226-L241
It’s expected to fail if:
the signer is not the admin of the group policy.
the new decision policy’s Validate() method doesn’t pass against the group.
The UpdateGroupPolicyMetadata can be used to update a group policy metadata.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L246-L259
It’s expected to fail if:
new metadata length is greater than MaxMetadataLen config.
the signer is not the admin of the group.
Msg/SubmitProposal
A new proposal can be created with the MsgSubmitProposal, which has a group policy account address, a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata.
An optional Exec value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L281-L315
It’s expected to fail if:
metadata, title, or summary length is greater than MaxMetadataLen config.
if any of the proposers is not a group member.
Msg/WithdrawProposal
A proposal can be withdrawn using MsgWithdrawProposal which has an address (can be either a proposer or the group policy admin) and a proposal_id (which has to be withdrawn).
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L323-L333
It’s expected to fail if:
the signer is neither the group policy admin nor proposer of the proposal.
the proposal is already closed or aborted.
Msg/Vote
A new vote can be created with the MsgVote, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata.
An optional Exec value can be provided to try to execute the proposal immediately after voting.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L338-L358
It’s expected to fail if:
metadata length is greater than MaxMetadataLen config.
the proposal is not in voting period anymore.
Msg/Exec
A proposal can be executed with the MsgExec.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L363-L373
The messages that are part of this proposal won’t be executed if:
the proposal has not been accepted by the group policy.
the proposal has already been successfully executed.
Msg/LeaveGroup
The MsgLeaveGroup allows group member to leave a group.
// Reference: https://github.com/cosmos/cosmos-sdk/tree/release/v0.50.x/proto/cosmos/group/v1/tx.proto#L381-L391
It’s expected to fail if:
the group member is not part of the group.
for any one of the associated group policies, if its decision policy’s Validate() method fails against the updated group.
Events
The group module emits the following events:
EventCreateGroup
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/CreateGroup cosmos.group.v1.EventCreateGroup group_id {groupId}
EventUpdateGroup
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/UpdateGroup{Admin|Metadata|Members}cosmos.group.v1.EventUpdateGroup group_id {groupId}
EventCreateGroupPolicy
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/CreateGroupPolicy cosmos.group.v1.EventCreateGroupPolicy address {groupPolicyAddress}
EventUpdateGroupPolicy
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/UpdateGroupPolicy{Admin|Metadata|DecisionPolicy}cosmos.group.v1.EventUpdateGroupPolicy address {groupPolicyAddress}
EventCreateProposal
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/CreateProposal cosmos.group.v1.EventCreateProposal proposal_id {proposalId}
EventWithdrawProposal
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/WithdrawProposal cosmos.group.v1.EventWithdrawProposal proposal_id {proposalId}
EventVote
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/Vote cosmos.group.v1.EventVote proposal_id {proposalId}
EventExec
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/Exec cosmos.group.v1.EventExec proposal_id {proposalId}cosmos.group.v1.EventExec logs {logs\_string}
EventLeaveGroup
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/LeaveGroup cosmos.group.v1.EventLeaveGroup proposal_id {proposalId}cosmos.group.v1.EventLeaveGroup address {address}
EventProposalPruned
Type Attribute Key Attribute Value message action /cosmos.group.v1.Msg/LeaveGroup cosmos.group.v1.EventProposalPruned proposal_id {proposalId}cosmos.group.v1.EventProposalPruned status {ProposalStatus}cosmos.group.v1.EventProposalPruned tally_result {TallyResult}
Client
CLI
A user can query and interact with the group module using the CLI.
Query
The query commands allow users to query group state.
group-info
The group-info command allows users to query for group info by given group id.
simd query group group-info [id] [flags]
Example:
simd query group group-info 1
Example Output:
admin: cosmos1..
group_id: "1"
metadata: AQ==
total_weight: "3"
version: "1"
group-policy-info
The group-policy-info command allows users to query for group policy info by account address of group policy .
simd query group group-policy-info [group-policy-account] [flags]
Example:
simd query group group-policy-info cosmos1..
Example Output:
address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
See all 11 lines
group-members
The group-members command allows users to query for group members by group id with pagination flags.
simd query group group-members [id] [flags]
Example:
simd query group group-members 1
Example Output:
members:
- group_id: "1"
member:
address: cosmos1..
metadata: AQ==
weight: "2"
- group_id: "1"
member:
address: cosmos1..
metadata: AQ==
weight: "1"
pagination:
next_key: null
total: "2"
See all 14 lines
groups-by-admin
The groups-by-admin command allows users to query for groups by admin account address with pagination flags.
simd query group groups-by-admin [admin] [flags]
Example:
simd query group groups-by-admin cosmos1..
Example Output:
groups:
- admin: cosmos1..
group_id: "1"
metadata: AQ==
total_weight: "3"
version: "1"
- admin: cosmos1..
group_id: "2"
metadata: AQ==
total_weight: "3"
version: "1"
pagination:
next_key: null
total: "2"
See all 14 lines
group-policies-by-group
The group-policies-by-group command allows users to query for group policies by group id with pagination flags.
simd query group group-policies-by-group [group-id] [flags]
Example:
simd query group group-policies-by-group 1
Example Output:
group_policies:
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
pagination:
next_key: null
total: "2"
See all 26 lines
group-policies-by-admin
The group-policies-by-admin command allows users to query for group policies by admin account address with pagination flags.
simd query group group-policies-by-admin [admin] [flags]
Example:
simd query group group-policies-by-admin cosmos1..
Example Output:
group_policies:
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
- address: cosmos1..
admin: cosmos1..
decision_policy:
'@type' : /cosmos.group.v1.ThresholdDecisionPolicy
threshold: "1"
windows:
min_execution_period: 0s
voting_period: 432000s
group_id: "1"
metadata: AQ==
version: "1"
pagination:
next_key: null
total: "2"
See all 26 lines
proposal
The proposal command allows users to query for proposal by id.
simd query group proposal [id] [flags]
Example:
simd query group proposal 1
Example Output:
proposal:
address: cosmos1..
executor_result: EXECUTOR_RESULT_NOT_RUN
group_policy_version: "1"
group_version: "1"
metadata: AQ==
msgs:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "100000000"
denom: stake
from_address: cosmos1..
to_address: cosmos1..
proposal_id: "1"
proposers:
- cosmos1..
result: RESULT_UNFINALIZED
status: STATUS_SUBMITTED
submitted_at: "2021-12-17T07:06:26.310638964Z"
windows:
min_execution_period: 0s
voting_period: 432000s
vote_state:
abstain_count: "0"
no_count: "0"
veto_count: "0"
yes_count: "0"
summary: "Summary"
title: "Title"
See all 29 lines
proposals-by-group-policy
The proposals-by-group-policy command allows users to query for proposals by account address of group policy with pagination flags.
simd query group proposals-by-group-policy [group-policy-account] [flags]
Example:
simd query group proposals-by-group-policy cosmos1..
Example Output:
pagination:
next_key: null
total: "1"
proposals:
- address: cosmos1..
executor_result: EXECUTOR_RESULT_NOT_RUN
group_policy_version: "1"
group_version: "1"
metadata: AQ==
msgs:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "100000000"
denom: stake
from_address: cosmos1..
to_address: cosmos1..
proposal_id: "1"
proposers:
- cosmos1..
result: RESULT_UNFINALIZED
status: STATUS_SUBMITTED
submitted_at: "2021-12-17T07:06:26.310638964Z"
windows:
min_execution_period: 0s
voting_period: 432000s
vote_state:
abstain_count: "0"
no_count: "0"
veto_count: "0"
yes_count: "0"
summary: "Summary"
title: "Title"
See all 32 lines
vote
The vote command allows users to query for vote by proposal id and voter account address.
simd query group vote [proposal-id] [voter] [flags]
Example:
simd query group vote 1 cosmos1..
Example Output:
vote:
choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
votes-by-proposal
The votes-by-proposal command allows users to query for votes by proposal id with pagination flags.
simd query group votes-by-proposal [proposal-id] [flags]
Example:
simd query group votes-by-proposal 1
Example Output:
pagination:
next_key: null
total: "1"
votes:
- choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
votes-by-voter
The votes-by-voter command allows users to query for votes by voter account address with pagination flags.
simd query group votes-by-voter [voter] [flags]
Example:
simd query group votes-by-voter cosmos1..
Example Output:
pagination:
next_key: null
total: "1"
votes:
- choice: CHOICE_YES
metadata: AQ==
proposal_id: "1"
submitted_at: "2021-12-17T08:05:02.490164009Z"
voter: cosmos1..
Transactions
The tx commands allow users to interact with the group module.
create-group
The create-group command allows users to create a group which is an aggregation of member accounts with associated weights and
an administrator account.
simd tx group create-group [admin] [metadata] [members-json-file]
Example:
simd tx group create-group cosmos1.. "AQ==" members.json
update-group-admin
The update-group-admin command allows users to update a group’s admin.
simd tx group update-group-admin [admin] [group-id] [new-admin] [flags]
Example:
simd tx group update-group-admin cosmos1.. 1 cosmos1..
update-group-members
The update-group-members command allows users to update a group’s members.
simd tx group update-group-members [admin] [group-id] [members-json-file] [flags]
Example:
simd tx group update-group-members cosmos1.. 1 members.json
The update-group-metadata command allows users to update a group’s metadata.
simd tx group update-group-metadata [admin] [group-id] [metadata] [flags]
Example:
simd tx group update-group-metadata cosmos1.. 1 "AQ=="
create-group-policy
The create-group-policy command allows users to create a group policy which is an account associated with a group and a decision policy.
simd tx group create-group-policy [admin] [group-id] [metadata] [decision-policy] [flags]
Example:
simd tx group create-group-policy cosmos1.. 1 "AQ==" '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
create-group-with-policy
The create-group-with-policy command allows users to create a group which is an aggregation of member accounts with associated weights and an administrator account with decision policy. If the --group-policy-as-admin flag is set to true, the group policy address becomes the group and group policy admin.
simd tx group create-group-with-policy [admin] [group-metadata] [group-policy-metadata] [members-json-file] [decision-policy] [flags]
Example:
simd tx group create-group-with-policy cosmos1.. "AQ==" "AQ==" members.json '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
update-group-policy-admin
The update-group-policy-admin command allows users to update a group policy admin.
simd tx group update-group-policy-admin [admin] [group-policy-account] [new-admin] [flags]
Example:
simd tx group update-group-policy-admin cosmos1.. cosmos1.. cosmos1..
The update-group-policy-metadata command allows users to update a group policy metadata.
simd tx group update-group-policy-metadata [admin] [group-policy-account] [new-metadata] [flags]
Example:
simd tx group update-group-policy-metadata cosmos1.. cosmos1.. "AQ=="
update-group-policy-decision-policy
The update-group-policy-decision-policy command allows users to update a group policy’s decision policy.
simd tx group update-group-policy-decision-policy [admin] [group-policy-account] [decision-policy] [flags]
Example:
simd tx group update-group-policy-decision-policy cosmos1.. cosmos1.. '{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"2", "windows": {"voting_period": "120h", "min_execution_period": "0s"}}'
submit-proposal
The submit-proposal command allows users to submit a new proposal.
simd tx group submit-proposal [group-policy-account] [proposer[,proposer] * ] [msg_tx_json_file] [metadata] [flags]
Example:
simd tx group submit-proposal cosmos1.. cosmos1.. msg_tx.json "AQ=="
withdraw-proposal
The withdraw-proposal command allows users to withdraw a proposal.
simd tx group withdraw-proposal [proposal-id] [group-policy-admin-or-proposer]
Example:
simd tx group withdraw-proposal 1 cosmos1..
vote
The vote command allows users to vote on a proposal.
simd tx group vote proposal-id] [voter] [choice] [metadata] [flags]
Example:
simd tx group vote 1 cosmos1.. CHOICE_YES "AQ=="
exec
The exec command allows users to execute a proposal.
simd tx group exec [proposal-id] [flags]
Example:
leave-group
The leave-group command allows group member to leave the group.
simd tx group leave-group [member-address] [group-id]
Example:
simd tx group leave-group cosmos1... 1
gRPC
A user can query the group module using gRPC endpoints.
GroupInfo
The GroupInfo endpoint allows users to query for group info by given group id.
cosmos.group.v1.Query/GroupInfo
Example:
grpcurl -plaintext \
-d '{"group_id":1}' localhost:9090 cosmos.group.v1.Query/GroupInfo
Example Output:
{
"info" : {
"groupId" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
}
}
GroupPolicyInfo
The GroupPolicyInfo endpoint allows users to query for group policy info by account address of group policy.
cosmos.group.v1.Query/GroupPolicyInfo
Example:
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPolicyInfo
Example Output:
{
"info" : {
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows": {"voting_period": "120h", "min_execution_period": "0s"}},
}
}
GroupMembers
The GroupMembers endpoint allows users to query for group members by group id with pagination flags.
cosmos.group.v1.Query/GroupMembers
Example:
grpcurl -plaintext \
-d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupMembers
Example Output:
{
"members" : [
{
"groupId" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "1"
}
},
{
"groupId" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "2"
}
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupsByAdmin
The GroupsByAdmin endpoint allows users to query for groups by admin account address with pagination flags.
cosmos.group.v1.Query/GroupsByAdmin
Example:
grpcurl -plaintext \
-d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupsByAdmin
Example Output:
{
"groups" : [
{
"groupId" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
},
{
"groupId" : "2",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"totalWeight" : "3"
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupPoliciesByGroup
The GroupPoliciesByGroup endpoint allows users to query for group policies by group id with pagination flags.
cosmos.group.v1.Query/GroupPoliciesByGroup
Example:
grpcurl -plaintext \
-d '{"group_id":"1"}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByGroup
Example Output:
{
"GroupPolicies" : [
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
},
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
GroupPoliciesByAdmin
The GroupPoliciesByAdmin endpoint allows users to query for group policies by admin account address with pagination flags.
cosmos.group.v1.Query/GroupPoliciesByAdmin
Example:
grpcurl -plaintext \
-d '{"admin":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/GroupPoliciesByAdmin
Example Output:
{
"GroupPolicies" : [
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
},
{
"address" : "cosmos1..",
"groupId" : "1",
"admin" : "cosmos1..",
"version" : "1",
"decisionPolicy" : {"@type":"/cosmos.group.v1.ThresholdDecisionPolicy","threshold":"1","windows":{"voting_period": "120h", "min_execution_period": "0s"}},
}
],
"pagination" : {
"total" : "2"
}
}
See all 21 lines
Proposal
The Proposal endpoint allows users to query for proposal by id.
cosmos.group.v1.Query/Proposal
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/Proposal
Example Output:
{
"proposal" : {
"proposalId" : "1",
"address" : "cosmos1..",
"proposers" : [
"cosmos1.."
],
"submittedAt" : "2021-12-17T07:06:26.310638964Z",
"groupVersion" : "1",
"GroupPolicyVersion" : "1",
"status" : "STATUS_SUBMITTED",
"result" : "RESULT_UNFINALIZED",
"voteState" : {
"yesCount" : "0",
"noCount" : "0",
"abstainCount" : "0",
"vetoCount" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executorResult" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{ "@type" : "/cosmos.bank.v1beta1.MsgSend" , "amount" : [{ " denom ":" stake "," amount ":" 100000000 "}]," fromAddress ":" cosmos1.. "," toAddress ":" cosmos1.. "}
],
" title ": " Title ",
" summary ": " Summary ",
}
}
See all 30 lines
ProposalsByGroupPolicy
The ProposalsByGroupPolicy endpoint allows users to query for proposals by account address of group policy with pagination flags.
cosmos.group.v1.Query/ProposalsByGroupPolicy
Example:
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/ProposalsByGroupPolicy
Example Output:
{
"proposals" : [
{
"proposalId" : "1",
"address" : "cosmos1..",
"proposers" : [
"cosmos1.."
],
"submittedAt" : "2021-12-17T08:03:27.099649352Z",
"groupVersion" : "1",
"GroupPolicyVersion" : "1",
"status" : "STATUS_CLOSED",
"result" : "RESULT_ACCEPTED",
"voteState" : {
"yesCount" : "1",
"noCount" : "0",
"abstainCount" : "0",
"vetoCount" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executorResult" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{ "@type" : "/cosmos.bank.v1beta1.MsgSend" , "amount" : [{ " denom ":" stake "," amount ":" 100000000 "}]," fromAddress ":" cosmos1.. "," toAddress ":" cosmos1.. "}
],
" title ": " Title ",
" summary ": " Summary ",
}
],
" pagination ": {
" total ": " 1 "
}
}
See all 35 lines
VoteByProposalVoter
The VoteByProposalVoter endpoint allows users to query for vote by proposal id and voter account address.
cosmos.group.v1.Query/VoteByProposalVoter
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1","voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VoteByProposalVoter
Example Output:
{
"vote" : {
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
}
VotesByProposal
The VotesByProposal endpoint allows users to query for votes by proposal id with pagination flags.
cosmos.group.v1.Query/VotesByProposal
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' localhost:9090 cosmos.group.v1.Query/VotesByProposal
Example Output:
{
"votes" : [
{
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"total" : "1"
}
}
See all 13 lines
VotesByVoter
The VotesByVoter endpoint allows users to query for votes by voter account address with pagination flags.
cosmos.group.v1.Query/VotesByVoter
Example:
grpcurl -plaintext \
-d '{"voter":"cosmos1.."}' localhost:9090 cosmos.group.v1.Query/VotesByVoter
Example Output:
{
"votes" : [
{
"proposalId" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"submittedAt" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"total" : "1"
}
}
See all 13 lines
REST
A user can query the group module using REST endpoints.
GroupInfo
The GroupInfo endpoint allows users to query for group info by given group id.
/cosmos/group/v1/group_info/ {group_id}
Example:
curl localhost:1317/cosmos/group/v1/group_info/1
Example Output:
{
"info" : {
"id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
}
}
GroupPolicyInfo
The GroupPolicyInfo endpoint allows users to query for group policy info by account address of group policy.
/cosmos/group/v1/group_policy_info/ {address}
Example:
curl localhost:1317/cosmos/group/v1/group_policy_info/cosmos1..
Example Output:
{
"info" : {
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
}
See all 17 lines
GroupMembers
The GroupMembers endpoint allows users to query for group members by group id with pagination flags.
/cosmos/group/v1/group_members/ {group_id}
Example:
curl localhost:1317/cosmos/group/v1/group_members/1
Example Output:
{
"members" : [
{
"group_id" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "1",
"metadata" : "AQ=="
}
},
{
"group_id" : "1",
"member" : {
"address" : "cosmos1..",
"weight" : "2",
"metadata" : "AQ=="
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 23 lines
GroupsByAdmin
The GroupsByAdmin endpoint allows users to query for groups by admin account address with pagination flags.
/cosmos/group/v1/groups_by_admin/ {admin}
Example:
curl localhost:1317/cosmos/group/v1/groups_by_admin/cosmos1..
Example Output:
{
"groups" : [
{
"id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
},
{
"id" : "2",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"total_weight" : "3"
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 22 lines
GroupPoliciesByGroup
The GroupPoliciesByGroup endpoint allows users to query for group policies by group id with pagination flags.
/cosmos/group/v1/group_policies_by_group/ {group_id}
Example:
curl localhost:1317/cosmos/group/v1/group_policies_by_group/1
Example Output:
{
"group_policies" : [
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
},
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
}
See all 38 lines
GroupPoliciesByAdmin
The GroupPoliciesByAdmin endpoint allows users to query for group policies by admin account address with pagination flags.
/cosmos/group/v1/group_policies_by_admin/ {admin}
Example:
curl localhost:1317/cosmos/group/v1/group_policies_by_admin/cosmos1..
Example Output:
{
"group_policies" : [
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
},
{
"address" : "cosmos1..",
"group_id" : "1",
"admin" : "cosmos1..",
"metadata" : "AQ==",
"version" : "1",
"decision_policy" : {
"@type" : "/cosmos.group.v1.ThresholdDecisionPolicy",
"threshold" : "1",
"windows" : {
"voting_period" : "120h",
"min_execution_period" : "0s"
}
},
}
],
"pagination" : {
"next_key" : null,
"total" : "2"
}
See all 37 lines
Proposal
The Proposal endpoint allows users to query for proposal by id.
/cosmos/group/v1/proposal/ {proposal_id}
Example:
curl localhost:1317/cosmos/group/v1/proposal/1
Example Output:
{
"proposal" : {
"proposal_id" : "1",
"address" : "cosmos1..",
"metadata" : "AQ==",
"proposers" : [
"cosmos1.."
],
"submitted_at" : "2021-12-17T07:06:26.310638964Z",
"group_version" : "1",
"group_policy_version" : "1",
"status" : "STATUS_SUBMITTED",
"result" : "RESULT_UNFINALIZED",
"vote_state" : {
"yes_count" : "0",
"no_count" : "0",
"abstain_count" : "0",
"veto_count" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executor_result" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{
"@type" : "/cosmos.bank.v1beta1.MsgSend",
"from_address" : "cosmos1..",
"to_address" : "cosmos1..",
"amount" : [
{
"denom" : "stake",
"amount" : "100000000"
}
]
}
],
"title" : "Title",
"summary" : "Summary",
}
}
See all 41 lines
ProposalsByGroupPolicy
The ProposalsByGroupPolicy endpoint allows users to query for proposals by account address of group policy with pagination flags.
/cosmos/group/v1/proposals_by_group_policy/ {address}
Example:
curl localhost:1317/cosmos/group/v1/proposals_by_group_policy/cosmos1..
Example Output:
{
"proposals" : [
{
"id" : "1",
"group_policy_address" : "cosmos1..",
"metadata" : "AQ==",
"proposers" : [
"cosmos1.."
],
"submit_time" : "2021-12-17T08:03:27.099649352Z",
"group_version" : "1",
"group_policy_version" : "1",
"status" : "STATUS_CLOSED",
"result" : "RESULT_ACCEPTED",
"vote_state" : {
"yes_count" : "1",
"no_count" : "0",
"abstain_count" : "0",
"veto_count" : "0"
},
"windows" : {
"min_execution_period" : "0s",
"voting_period" : "432000s"
},
"executor_result" : "EXECUTOR_RESULT_NOT_RUN",
"messages" : [
{
"@type" : "/cosmos.bank.v1beta1.MsgSend",
"from_address" : "cosmos1..",
"to_address" : "cosmos1..",
"amount" : [
{
"denom" : "stake",
"amount" : "100000000"
}
]
}
]
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 45 lines
VoteByProposalVoter
The VoteByProposalVoter endpoint allows users to query for vote by proposal id and voter account address.
/cosmos/group/v1/vote_by_proposal_voter/ {proposal_id} / {voter}
Example:
curl localhost:1317/cosmos/group/v1beta1/vote_by_proposal_voter/1/cosmos1..
Example Output:
{
"vote" : {
"proposal_id" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"metadata" : "AQ==",
"submitted_at" : "2021-12-17T08:05:02.490164009Z"
}
}
VotesByProposal
The VotesByProposal endpoint allows users to query for votes by proposal id with pagination flags.
/cosmos/group/v1/votes_by_proposal/ {proposal_id}
Example:
curl localhost:1317/cosmos/group/v1/votes_by_proposal/1
Example Output:
{
"votes" : [
{
"proposal_id" : "1",
"voter" : "cosmos1..",
"option" : "CHOICE_YES",
"metadata" : "AQ==",
"submit_time" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 15 lines
VotesByVoter
The VotesByVoter endpoint allows users to query for votes by voter account address with pagination flags.
/cosmos/group/v1/votes_by_voter/ {voter}
Example:
curl localhost:1317/cosmos/group/v1/votes_by_voter/cosmos1..
Example Output:
{
"votes" : [
{
"proposal_id" : "1",
"voter" : "cosmos1..",
"choice" : "CHOICE_YES",
"metadata" : "AQ==",
"submitted_at" : "2021-12-17T08:05:02.490164009Z"
}
],
"pagination" : {
"next_key" : null,
"total" : "1"
}
}
See all 15 lines
The group module has four locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the group and gov modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure across chains.
Proposal
Location: off-chain as json object stored on IPFS (mirrors gov proposal )
{
"title" : "" ,
"authors" : [ "" ],
"summary" : "" ,
"details" : "" ,
"proposal_forum_url" : "" ,
"vote_option_context" : "" ,
}
The authors field is an array of strings, this is to allow for multiple authors to be listed in the metadata.
In v0.46, the authors field is a comma-separated string. Frontends are encouraged to support both formats for backwards compatibility.
Vote
Location: on-chain as json within 255 character limit (mirrors gov vote )
Group
Location: off-chain as json object stored on IPFS
{
"name" : "" ,
"description" : "" ,
"group_website_url" : "" ,
"group_forum_url" : "" ,
}
Decision policy
Location: on-chain as json within 255 character limit
{
"name" : "" ,
"description" : "" ,
}