feat: Add simulations to group module (#10723)

## Description

Closes: #9901



---

### 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
- [ ] 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
- [ ] 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)
- [ ] 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
2022-01-21 10:52:26 +00:00
committed by GitHub
parent fd5b97bd7b
commit f52d87003c
21 changed files with 2215 additions and 192 deletions
+57
View File
@@ -0,0 +1,57 @@
package simulation
import (
"bytes"
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/keeper"
)
// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
// Value to the corresponding group type.
func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string {
return func(kvA, kvB kv.Pair) string {
switch {
case bytes.Equal(kvA.Key[:1], []byte{keeper.GroupTablePrefix}):
var groupA, groupB group.GroupInfo
cdc.MustUnmarshal(kvA.Value, &groupA)
cdc.MustUnmarshal(kvB.Value, &groupB)
return fmt.Sprintf("%v\n%v", groupA, groupB)
case bytes.Equal(kvA.Key[:1], []byte{keeper.GroupMemberTablePrefix}):
var memberA, memberB group.GroupMember
cdc.MustUnmarshal(kvA.Value, &memberA)
cdc.MustUnmarshal(kvB.Value, &memberB)
return fmt.Sprintf("%v\n%v", memberA, memberB)
case bytes.Equal(kvA.Key[:1], []byte{keeper.GroupPolicyTablePrefix}):
var accA, accB group.GroupPolicyInfo
cdc.MustUnmarshal(kvA.Value, &accA)
cdc.MustUnmarshal(kvB.Value, &accB)
return fmt.Sprintf("%v\n%v", accA, accB)
case bytes.Equal(kvA.Key[:1], []byte{keeper.ProposalTablePrefix}):
var propA, propB group.Proposal
cdc.MustUnmarshal(kvA.Value, &propA)
cdc.MustUnmarshal(kvB.Value, &propB)
return fmt.Sprintf("%v\n%v", propA, propB)
case bytes.Equal(kvA.Key[:1], []byte{keeper.VoteTablePrefix}):
var voteA, voteB group.Vote
cdc.MustUnmarshal(kvA.Value, &voteA)
cdc.MustUnmarshal(kvB.Value, &voteB)
return fmt.Sprintf("%v\n%v", voteA, voteB)
default:
panic(fmt.Sprintf("invalid group key %X", kvA.Key))
}
}
}
+80
View File
@@ -0,0 +1,80 @@
package simulation_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/internal/orm"
"github.com/cosmos/cosmos-sdk/x/group/keeper"
"github.com/cosmos/cosmos-sdk/x/group/simulation"
)
func TestDecodeStore(t *testing.T) {
cdc := simapp.MakeTestEncodingConfig().Codec
dec := simulation.NewDecodeStore(cdc)
g := group.GroupInfo{GroupId: 1}
groupBz, err := cdc.Marshal(&g)
require.NoError(t, err)
_, _, addr := testdata.KeyTestPubAddr()
member := group.GroupMember{GroupId: 1, Member: &group.Member{
Address: addr.String(),
}}
memberBz, err := cdc.Marshal(&member)
require.NoError(t, err)
_, _, accAddr := testdata.KeyTestPubAddr()
acc := group.GroupPolicyInfo{Address: accAddr.String()}
accBz, err := cdc.Marshal(&acc)
require.NoError(t, err)
proposal := group.Proposal{ProposalId: 1}
proposalBz, err := cdc.Marshal(&proposal)
require.NoError(t, err)
vote := group.Vote{Voter: addr.String(), ProposalId: 1}
voteBz, err := cdc.Marshal(&vote)
require.NoError(t, err)
kvPairs := kv.Pairs{
Pairs: []kv.Pair{
{Key: append([]byte{keeper.GroupTablePrefix}, orm.PrimaryKey(&g)...), Value: groupBz},
{Key: append([]byte{keeper.GroupMemberTablePrefix}, orm.PrimaryKey(&member)...), Value: memberBz},
{Key: append([]byte{keeper.GroupPolicyTablePrefix}, orm.PrimaryKey(&acc)...), Value: accBz},
{Key: append([]byte{keeper.ProposalTablePrefix}, orm.PrimaryKey(&proposal)...), Value: proposalBz},
{Key: append([]byte{keeper.VoteTablePrefix}, orm.PrimaryKey(&vote)...), Value: voteBz},
{Key: []byte{0x99}, Value: []byte{0x99}},
},
}
tests := []struct {
name string
expectErr bool
expectedLog string
}{
{"Group", false, fmt.Sprintf("%v\n%v", g, g)},
{"GroupMember", false, fmt.Sprintf("%v\n%v", member, member)},
{"GroupPolicy", false, fmt.Sprintf("%v\n%v", acc, acc)},
{"Proposal", false, fmt.Sprintf("%v\n%v", proposal, proposal)},
{"Vote", false, fmt.Sprintf("%v\n%v", vote, vote)},
{"other", true, ""},
}
for i, tt := range tests {
i, tt := i, tt
t.Run(tt.name, func(t *testing.T) {
if tt.expectErr {
require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name)
} else {
require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name)
}
})
}
}
+199
View File
@@ -0,0 +1,199 @@
package simulation
import (
"math/rand"
"time"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/group"
)
const (
GroupInfo = "group-info"
GroupMembers = "group-members"
GroupPolicyInfo = "group-policy-info"
GroupProposals = "group-proposals"
GroupVote = "group-vote"
)
func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo {
groups := make([]*group.GroupInfo, 3)
for i := 0; i < 3; i++ {
acc, _ := simtypes.RandomAcc(r, accounts)
groups[i] = &group.GroupInfo{
GroupId: uint64(i + 1),
Admin: acc.Address.String(),
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
Version: 1,
TotalWeight: "10",
}
}
return groups
}
func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMember {
groupMembers := make([]*group.GroupMember, 3)
for i := 0; i < 3; i++ {
acc, _ := simtypes.RandomAcc(r, accounts)
groupMembers[i] = &group.GroupMember{
GroupId: uint64(i + 1),
Member: &group.Member{
Address: acc.Address.String(),
Weight: "10",
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
},
}
}
return groupMembers
}
func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.GroupPolicyInfo {
groupPolicies := make([]*group.GroupPolicyInfo, 3)
for i := 0; i < 3; i++ {
acc, _ := simtypes.RandomAcc(r, simState.Accounts)
any, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", time.Second*time.Duration(1)))
if err != nil {
panic(err)
}
groupPolicies[i] = &group.GroupPolicyInfo{
GroupId: uint64(i + 1),
Admin: acc.Address.String(),
Address: acc.Address.String(),
Version: 1,
DecisionPolicy: any,
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
}
}
return groupPolicies
}
func getProposals(r *rand.Rand, simState *module.SimulationState) []*group.Proposal {
proposals := make([]*group.Proposal, 3)
proposers := []string{simState.Accounts[0].Address.String(), simState.Accounts[1].Address.String()}
for i := 0; i < 3; i++ {
from, _ := simtypes.RandomAcc(r, simState.Accounts)
to, _ := simtypes.RandomAcc(r, simState.Accounts)
fromAddr := from.Address.String()
submittedAt := time.Unix(0, 0)
timeout := submittedAt.Add(time.Second * 1000).UTC()
proposal := &group.Proposal{
ProposalId: uint64(i + 1),
Proposers: proposers,
Address: fromAddr,
GroupVersion: uint64(i + 1),
GroupPolicyVersion: uint64(i + 1),
Status: group.ProposalStatusSubmitted,
Result: group.ProposalResultAccepted,
VoteState: group.Tally{
YesCount: "1",
NoCount: "1",
AbstainCount: "1",
VetoCount: "0",
},
ExecutorResult: group.ProposalExecutorResultNotRun,
Metadata: []byte(simtypes.RandStringOfLength(r, 50)),
SubmittedAt: submittedAt,
Timeout: timeout,
}
err := proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{
FromAddress: fromAddr,
ToAddress: to.Address.String(),
Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)),
}})
if err != nil {
panic(err)
}
proposals[i] = proposal
}
return proposals
}
func getVotes(r *rand.Rand, simState *module.SimulationState) []*group.Vote {
votes := make([]*group.Vote, 3)
for i := 0; i < 3; i++ {
votes[i] = &group.Vote{
ProposalId: uint64(i + 1),
Voter: simState.Accounts[i].Address.String(),
Choice: getVoteChoice(i),
Metadata: []byte(simtypes.RandStringOfLength(r, 50)),
SubmittedAt: time.Unix(0, 0),
}
}
return votes
}
func getVoteChoice(index int) group.Choice {
switch index {
case 0:
return group.Choice_CHOICE_YES
case 1:
return group.Choice_CHOICE_NO
case 2:
return group.Choice_CHOICE_ABSTAIN
default:
return group.Choice_CHOICE_VETO
}
}
// RandomizedGenState generates a random GenesisState for the group module.
func RandomizedGenState(simState *module.SimulationState) {
// groups
var groups []*group.GroupInfo
simState.AppParams.GetOrGenerate(
simState.Cdc, GroupInfo, &groups, simState.Rand,
func(r *rand.Rand) { groups = getGroups(r, simState.Accounts) },
)
// group members
var members []*group.GroupMember
simState.AppParams.GetOrGenerate(
simState.Cdc, GroupMembers, &members, simState.Rand,
func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts) },
)
// group accounts
var groupPolicies []*group.GroupPolicyInfo
simState.AppParams.GetOrGenerate(
simState.Cdc, GroupPolicyInfo, &groupPolicies, simState.Rand,
func(r *rand.Rand) { groupPolicies = getGroupPolicies(r, simState) },
)
// proposals
var proposals []*group.Proposal
simState.AppParams.GetOrGenerate(
simState.Cdc, GroupProposals, &proposals, simState.Rand,
func(r *rand.Rand) { proposals = getProposals(r, simState) },
)
// votes
var votes []*group.Vote
simState.AppParams.GetOrGenerate(
simState.Cdc, GroupVote, &votes, simState.Rand,
func(r *rand.Rand) { votes = getVotes(r, simState) },
)
groupGenesis := group.GenesisState{
GroupSeq: 3,
Groups: groups,
GroupMembers: members,
GroupPolicySeq: 3,
GroupPolicies: groupPolicies,
ProposalSeq: 3,
Proposals: proposals,
Votes: votes,
}
simState.GenState[group.ModuleName] = simState.Cdc.MustMarshalJSON(&groupGenesis)
}
+46
View File
@@ -0,0 +1,46 @@
package simulation_test
import (
"encoding/json"
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/simulation"
)
func TestRandomizedGenState(t *testing.T) {
app := simapp.Setup(t, false)
s := rand.NewSource(1)
r := rand.New(s)
simState := module.SimulationState{
AppParams: make(simtypes.AppParams),
Cdc: app.AppCodec(),
Rand: r,
NumBonded: 3,
Accounts: simtypes.RandomAccounts(r, 3),
InitialStake: 1000,
GenState: make(map[string]json.RawMessage),
}
simulation.RandomizedGenState(&simState)
var groupGenesis group.GenesisState
simState.Cdc.MustUnmarshalJSON(simState.GenState[group.ModuleName], &groupGenesis)
require.Equal(t, int(groupGenesis.GroupSeq), len(simState.Accounts))
require.Len(t, groupGenesis.Groups, len(simState.Accounts))
require.Len(t, groupGenesis.GroupMembers, len(simState.Accounts))
require.Equal(t, int(groupGenesis.GroupPolicySeq), len(simState.Accounts))
require.Len(t, groupGenesis.GroupPolicies, len(simState.Accounts))
require.Equal(t, int(groupGenesis.ProposalSeq), len(simState.Accounts))
require.Len(t, groupGenesis.Proposals, len(simState.Accounts))
require.Len(t, groupGenesis.Votes, len(simState.Accounts))
}
+999
View File
@@ -0,0 +1,999 @@
package simulation
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/simapp/helpers"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/group/keeper"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/group"
)
var initialGroupID = uint64(100000000000000)
// group message types
var (
TypeMsgCreateGroup = sdk.MsgTypeURL(&group.MsgCreateGroup{})
TypeMsgUpdateGroupMembers = sdk.MsgTypeURL(&group.MsgUpdateGroupMembers{})
TypeMsgUpdateGroupAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAdmin{})
TypeMsgUpdateGroupMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupMetadata{})
TypeMsgCreateGroupPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupPolicy{})
TypeMsgUpdateGroupPolicyAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyAdmin{})
TypeMsgUpdateGroupPolicyDecisionPolicy = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyDecisionPolicy{})
TypeMsgUpdateGroupPolicyMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyMetadata{})
TypeMsgCreateProposal = sdk.MsgTypeURL(&group.MsgCreateProposal{})
TypeMsgVote = sdk.MsgTypeURL(&group.MsgVote{})
TypeMsgExec = sdk.MsgTypeURL(&group.MsgExec{})
)
// Simulation operation weights constants
const (
OpMsgCreateGroup = "op_weight_msg_create_group"
OpMsgUpdateGroupAdmin = "op_weight_msg_update_group_admin"
OpMsgUpdateGroupMetadata = "op_wieght_msg_update_group_metadata"
OpMsgUpdateGroupMembers = "op_weight_msg_update_group_members"
OpMsgCreateGroupPolicy = "op_weight_msg_create_group_account"
OpMsgUpdateGroupPolicyAdmin = "op_weight_msg_update_group_account_admin"
OpMsgUpdateGroupPolicyDecisionPolicy = "op_weight_msg_update_group_account_decision_policy"
OpMsgUpdateGroupPolicyMetaData = "op_weight_msg_update_group_account_metadata"
OpMsgCreateProposal = "op_weight_msg_create_proposal"
OpMsgVote = "op_weight_msg_vote"
OpMsgExec = "ops_weight_msg_exec"
)
// If update group or group account txn's executed, `SimulateMsgVote` & `SimulateMsgExec` txn's returns `noOp`.
// That's why we have less weight for update group & group-account txn's.
const (
WeightMsgCreateGroup = 100
WeightMsgCreateGroupPolicy = 100
WeightMsgCreateProposal = 90
WeightMsgVote = 90
WeightMsgExec = 90
WeightMsgUpdateGroupMetadata = 5
WeightMsgUpdateGroupAdmin = 5
WeightMsgUpdateGroupMembers = 5
WeightMsgUpdateGroupPolicyAdmin = 5
WeightMsgUpdateGroupPolicyDecisionPolicy = 5
WeightMsgUpdateGroupPolicyMetadata = 5
)
const GroupMemberWeight = 40
// WeightedOperations returns all the operations from the module with their respective weights
func WeightedOperations(
appParams simtypes.AppParams, cdc codec.JSONCodec, ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper, appCdc cdctypes.AnyUnpacker) simulation.WeightedOperations {
var (
weightMsgCreateGroup int
weightMsgUpdateGroupAdmin int
weightMsgUpdateGroupMetadata int
weightMsgUpdateGroupMembers int
weightMsgCreateGroupPolicy int
weightMsgUpdateGroupPolicyAdmin int
weightMsgUpdateGroupPolicyDecisionPolicy int
weightMsgUpdateGroupPolicyMetadata int
weightMsgCreateProposal int
weightMsgVote int
weightMsgExec int
)
appParams.GetOrGenerate(cdc, OpMsgCreateGroup, &weightMsgCreateGroup, nil,
func(_ *rand.Rand) {
weightMsgCreateGroup = WeightMsgCreateGroup
},
)
appParams.GetOrGenerate(cdc, OpMsgCreateGroupPolicy, &weightMsgCreateGroupPolicy, nil,
func(_ *rand.Rand) {
weightMsgCreateGroupPolicy = WeightMsgCreateGroupPolicy
},
)
appParams.GetOrGenerate(cdc, OpMsgCreateProposal, &weightMsgCreateProposal, nil,
func(_ *rand.Rand) {
weightMsgCreateProposal = WeightMsgCreateProposal
},
)
appParams.GetOrGenerate(cdc, OpMsgVote, &weightMsgVote, nil,
func(_ *rand.Rand) {
weightMsgVote = WeightMsgVote
},
)
appParams.GetOrGenerate(cdc, OpMsgExec, &weightMsgExec, nil,
func(_ *rand.Rand) {
weightMsgExec = WeightMsgExec
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupMetadata, &weightMsgUpdateGroupMetadata, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupMetadata = WeightMsgUpdateGroupMetadata
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupAdmin, &weightMsgUpdateGroupAdmin, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupAdmin = WeightMsgUpdateGroupAdmin
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupMembers, &weightMsgUpdateGroupMembers, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupMembers = WeightMsgUpdateGroupMembers
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupPolicyAdmin, &weightMsgUpdateGroupPolicyAdmin, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupPolicyAdmin = WeightMsgUpdateGroupPolicyAdmin
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupPolicyDecisionPolicy, &weightMsgUpdateGroupPolicyDecisionPolicy, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupPolicyDecisionPolicy = WeightMsgUpdateGroupPolicyDecisionPolicy
},
)
appParams.GetOrGenerate(cdc, OpMsgUpdateGroupPolicyMetaData, &weightMsgUpdateGroupPolicyMetadata, nil,
func(_ *rand.Rand) {
weightMsgUpdateGroupPolicyMetadata = WeightMsgUpdateGroupPolicyMetadata
},
)
return simulation.WeightedOperations{
simulation.NewWeightedOperation(
weightMsgCreateGroup,
SimulateMsgCreateGroup(ak, bk),
),
simulation.NewWeightedOperation(
weightMsgCreateGroupPolicy,
SimulateMsgCreateGroupPolicy(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgCreateProposal,
SimulateMsgCreateProposal(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgVote,
SimulateMsgVote(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgExec,
SimulateMsgExec(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupMetadata,
SimulateMsgUpdateGroupMetadata(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupAdmin,
SimulateMsgUpdateGroupAdmin(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupMembers,
SimulateMsgUpdateGroupMembers(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupPolicyAdmin,
SimulateMsgUpdateGroupPolicyAdmin(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupPolicyDecisionPolicy,
SimulateMsgUpdateGroupPolicyDecisionPolicy(ak, bk, k),
),
simulation.NewWeightedOperation(
weightMsgUpdateGroupPolicyMetadata,
SimulateMsgUpdateGroupPolicyMetadata(ak, bk, k),
),
}
}
// SimulateMsgCreateGroup generates a MsgCreateGroup with random values
func SimulateMsgCreateGroup(ak group.AccountKeeper, bk group.BankKeeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
acc, _ := simtypes.RandomAcc(r, accounts)
account := ak.GetAccount(ctx, acc.Address)
accAddr := acc.Address.String()
spendableCoins := bk.SpendableCoins(ctx, account.GetAddress())
fees, err := simtypes.RandomFees(r, ctx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err
}
members := []group.Member{
{
Address: accAddr,
Weight: fmt.Sprintf("%d", GroupMemberWeight),
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
},
}
msg := &group.MsgCreateGroup{Admin: accAddr, Members: members, Metadata: []byte(simtypes.RandStringOfLength(r, 10))}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(msg, true, "", nil), nil, err
}
}
// SimulateMsgCreateGroupPolicy generates a NewMsgCreateGroupPolicy with random values
func SimulateMsgCreateGroupPolicy(ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, err
}
if groupInfo == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, nil
}
groupID := groupInfo.GroupId
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "fee error"), nil, err
}
msg, err := group.NewMsgCreateGroupPolicy(
acc.Address,
groupID,
[]byte(simtypes.RandStringOfLength(r, 10)),
&group.ThresholdDecisionPolicy{
Threshold: "20",
Timeout: time.Second * time.Duration(30*24*60*60),
},
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, err.Error()), nil, err
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
fmt.Printf("ERR DELIVER %v\n", err)
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(msg, true, "", nil), nil, err
}
}
// SimulateMsgCreateProposal generates a NewMsgCreateProposal with random values
func SimulateMsgCreateProposal(ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, ""), nil, err
}
if g == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "no group found"), nil, nil
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "no group policy found"), nil, nil
}
groupID := g.GroupId
groupPolicyAddr := groupPolicy.Address
// Return a no-op if we know the proposal cannot be created
policy := groupPolicy.GetDecisionPolicy()
err = policy.Validate(*g)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, ""), nil, nil
}
// Pick a random member from the group
ctx := sdk.WrapSDKContext(sdkCtx)
acc, account, err := randomMember(r, k, ak, ctx, accounts, groupID)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, ""), nil, err
}
if account == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "no group member found"), nil, nil
}
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "fee error"), nil, err
}
msg := group.MsgCreateProposal{
Address: groupPolicyAddr,
Proposers: []string{acc.Address.String()},
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// SimulateMsgUpdateGroupAdmin generates a MsgUpdateGroupAdmin with random values
func SimulateMsgUpdateGroupAdmin(ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, err
}
if groupInfo == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, nil
}
groupID := groupInfo.GroupId
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "fee error"), nil, err
}
if len(accounts) == 1 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "can't set a new admin with only one account"), nil, nil
}
newAdmin, _ := simtypes.RandomAcc(r, accounts)
// disallow setting current admin as new admin
for acc.PubKey.Equals(newAdmin.PubKey) {
newAdmin, _ = simtypes.RandomAcc(r, accounts)
}
msg := group.MsgUpdateGroupAdmin{
GroupId: groupID,
Admin: account.GetAddress().String(),
NewAdmin: newAdmin.Address.String(),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// SimulateMsgUpdateGroupMetadata generates a MsgUpdateGroupMetadata with random values
func SimulateMsgUpdateGroupMetadata(ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, err
}
if groupInfo == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, nil
}
groupID := groupInfo.GroupId
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "fee error"), nil, err
}
msg := group.MsgUpdateGroupMetadata{
GroupId: groupID,
Admin: account.GetAddress().String(),
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// SimulateMsgUpdateGroupMembers generates a MsgUpdateGroupMembers with random values
func SimulateMsgUpdateGroupMembers(ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, err
}
if groupInfo == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, nil
}
groupID := groupInfo.GroupId
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "fee error"), nil, err
}
member, _ := simtypes.RandomAcc(r, accounts)
members := []group.Member{
{
Address: member.Address.String(),
Weight: fmt.Sprintf("%d", GroupMemberWeight),
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
},
}
msg := group.MsgUpdateGroupMembers{
GroupId: groupID,
Admin: acc.Address.String(),
MemberUpdates: members,
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// SimulateMsgUpdateGroupPolicyAdmin generates a MsgUpdateGroupPolicyAdmin with random values
func SimulateMsgUpdateGroupPolicyAdmin(ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
_, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, ""), nil, err
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "no group policy found"), nil, nil
}
groupPolicyAddr := groupPolicy.Address
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "fee error"), nil, err
}
if len(accounts) == 1 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "can't set a new admin with only one account"), nil, nil
}
newAdmin, _ := simtypes.RandomAcc(r, accounts)
// disallow setting current admin as new admin
for acc.PubKey.Equals(newAdmin.PubKey) {
newAdmin, _ = simtypes.RandomAcc(r, accounts)
}
msg := group.MsgUpdateGroupPolicyAdmin{
Admin: acc.Address.String(),
Address: groupPolicyAddr,
NewAdmin: newAdmin.Address.String(),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// // SimulateMsgUpdateGroupPolicyDecisionPolicy generates a NewMsgUpdateGroupPolicyDecisionPolicyRequest with random values
func SimulateMsgUpdateGroupPolicyDecisionPolicy(ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
_, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, ""), nil, err
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "no group policy found"), nil, nil
}
groupPolicyAddr := groupPolicy.Address
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "fee error"), nil, err
}
groupPolicyBech32, err := sdk.AccAddressFromBech32(groupPolicyAddr)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil
}
msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicyRequest(acc.Address, groupPolicyBech32, &group.ThresholdDecisionPolicy{
Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 20)),
Timeout: time.Second * time.Duration(simtypes.RandIntBetween(r, 100, 1000)),
})
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, err.Error()), nil, err
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(msg, true, "", nil), nil, err
}
}
// // SimulateMsgUpdateGroupPolicyMetadata generates a MsgUpdateGroupPolicyMetadata with random values
func SimulateMsgUpdateGroupPolicyMetadata(ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
_, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, ""), nil, err
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "no group policy found"), nil, nil
}
groupPolicyAddr := groupPolicy.Address
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "fee error"), nil, err
}
msg := group.MsgUpdateGroupPolicyMetadata{
Admin: acc.Address.String(),
Address: groupPolicyAddr,
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// SimulateMsgVote generates a MsgVote with random values
func SimulateMsgVote(ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err
}
if g == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group found"), nil, nil
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group policy found"), nil, nil
}
groupPolicyAddr := groupPolicy.Address
// Pick a random member from the group
ctx := sdk.WrapSDKContext(sdkCtx)
acc, account, err := randomMember(r, k, ak, ctx, accounts, g.GroupId)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err
}
if account == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group member found"), nil, nil
}
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err
}
proposalsResult, err := k.ProposalsByGroupPolicy(ctx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr})
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err
}
proposals := proposalsResult.GetProposals()
if len(proposals) == 0 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil
}
var proposal *group.Proposal
proposalID := -1
for _, p := range proposals {
if p.Status == group.ProposalStatusSubmitted {
timeout := p.Timeout
proposal = p
proposalID = int(p.ProposalId)
if timeout.Before(sdkCtx.BlockTime()) || timeout.Equal(sdkCtx.BlockTime()) {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "voting period ended: skipping"), nil, nil
}
break
}
}
// return no-op if no proposal found
if proposalID == -1 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil
}
// Ensure that group and group policy haven't been modified since the proposal submission.
if proposal.GroupPolicyVersion != groupPolicy.Version {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "group policy has been modified"), nil, nil
}
if proposal.GroupVersion != g.Version {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "group has been modified"), nil, nil
}
// Ensure member hasn't already voted
res, _ := k.VoteByProposalVoter(ctx, &group.QueryVoteByProposalVoterRequest{
Voter: acc.Address.String(),
ProposalId: uint64(proposalID),
})
if res != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "member has already voted"), nil, nil
}
msg := group.MsgVote{
ProposalId: uint64(proposalID),
Voter: acc.Address.String(),
Choice: group.Choice_CHOICE_YES,
Metadata: []byte(simtypes.RandStringOfLength(r, 10)),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group account was modified") {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "no-op:group/group-account was modified"), nil, nil
}
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
// // SimulateMsgExec generates a MsgExec with random values
func SimulateMsgExec(ak group.AccountKeeper,
bk group.BankKeeper, k keeper.Keeper) simtypes.Operation {
return func(
r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
_, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, ""), nil, err
}
if groupPolicy == nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no group policy found"), nil, nil
}
groupPolicyAddr := groupPolicy.Address
spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress())
fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fee error"), nil, err
}
ctx := sdk.WrapSDKContext(sdkCtx)
proposalsResult, err := k.ProposalsByGroupPolicy(ctx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr})
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fail to query group info"), nil, err
}
proposals := proposalsResult.GetProposals()
if len(proposals) == 0 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil
}
proposalID := -1
for _, proposal := range proposals {
if proposal.Status == group.ProposalStatusClosed {
proposalID = int(proposal.ProposalId)
break
}
}
// return no-op if no proposal found
if proposalID == -1 {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil
}
msg := group.MsgExec{
ProposalId: uint64(proposalID),
Signer: acc.Address.String(),
}
txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
txGen,
[]sdk.Msg{&msg},
fees,
helpers.DefaultGenTxGas,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
acc.PrivKey,
)
if err != nil {
return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err
}
_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group account was modified") {
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "no-op:group/group-account was modified"), nil, nil
}
return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err
}
return simtypes.NewOperationMsg(&msg, true, "", nil), nil, err
}
}
func randomGroup(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper,
ctx sdk.Context, accounts []simtypes.Account) (groupInfo *group.GroupInfo, acc simtypes.Account, account authtypes.AccountI, err error) {
groupID := k.GetGroupSequence(ctx)
switch {
case groupID > initialGroupID:
// select a random ID between [initialGroupID, groupID]
groupID = uint64(simtypes.RandIntBetween(r, int(initialGroupID), int(groupID)))
default:
// This is called on the first call to this function
// in order to update the global variable
initialGroupID = groupID
}
res, err := k.GroupInfo(sdk.WrapSDKContext(ctx), &group.QueryGroupInfoRequest{GroupId: groupID})
if err != nil {
return nil, simtypes.Account{}, nil, err
}
groupInfo = res.Info
groupAdmin := groupInfo.Admin
found := -1
for i := range accounts {
if accounts[i].Address.String() == groupAdmin {
found = i
break
}
}
if found < 0 {
return nil, simtypes.Account{}, nil, nil
}
acc = accounts[found]
account = ak.GetAccount(ctx, acc.Address)
return groupInfo, acc, account, nil
}
func randomGroupPolicy(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper,
ctx sdk.Context, accounts []simtypes.Account) (groupInfo *group.GroupInfo, groupPolicyInfo *group.GroupPolicyInfo, acc simtypes.Account, account authtypes.AccountI, err error) {
groupInfo, _, _, err = randomGroup(r, k, ak, ctx, accounts)
if err != nil {
return nil, nil, simtypes.Account{}, nil, err
}
if groupInfo == nil {
return nil, nil, simtypes.Account{}, nil, nil
}
groupID := groupInfo.GroupId
result, err := k.GroupPoliciesByGroup(sdk.WrapSDKContext(ctx), &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID})
if err != nil {
return groupInfo, nil, simtypes.Account{}, nil, err
}
n := randIntInRange(r, len(result.GroupPolicies))
if n < 0 {
return groupInfo, nil, simtypes.Account{}, nil, nil
}
groupPolicyInfo = result.GroupPolicies[n]
idx := findAccount(accounts, groupPolicyInfo.Admin)
if idx < 0 {
return groupInfo, nil, simtypes.Account{}, nil, nil
}
acc = accounts[idx]
account = ak.GetAccount(ctx, acc.Address)
return groupInfo, groupPolicyInfo, acc, account, nil
}
func randomMember(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper,
ctx context.Context, accounts []simtypes.Account, groupID uint64) (acc simtypes.Account, account authtypes.AccountI, err error) {
res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{
GroupId: groupID,
})
if err != nil {
return simtypes.Account{}, nil, err
}
n := randIntInRange(r, len(res.Members))
if n < 0 {
return simtypes.Account{}, nil, err
}
idx := findAccount(accounts, res.Members[n].Member.Address)
if idx < 0 {
return simtypes.Account{}, nil, err
}
acc = accounts[idx]
account = ak.GetAccount(sdk.UnwrapSDKContext(ctx), acc.Address)
return acc, account, nil
}
func randIntInRange(r *rand.Rand, l int) int {
if l == 0 {
return -1
}
if l == 1 {
return 0
} else {
return simtypes.RandIntBetween(r, 0, l-1)
}
}
func findAccount(accounts []simtypes.Account, addr string) (idx int) {
idx = -1
for i := range accounts {
if accounts[i].Address.String() == addr {
idx = i
break
}
}
return idx
}
+650
View File
@@ -0,0 +1,650 @@
package simulation_test
import (
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/simulation"
)
type SimTestSuite struct {
suite.Suite
ctx sdk.Context
app *simapp.SimApp
}
func (suite *SimTestSuite) SetupTest() {
checkTx := false
app := simapp.Setup(suite.T(), checkTx)
suite.app = app
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{})
}
func (suite *SimTestSuite) TestWeightedOperations() {
cdc := suite.app.AppCodec()
appParams := make(simtypes.AppParams)
weightedOps := simulation.WeightedOperations(appParams, cdc, suite.app.AccountKeeper,
suite.app.BankKeeper, suite.app.GroupKeeper, cdc,
)
s := rand.NewSource(1)
r := rand.New(s)
accs := suite.getTestingAccounts(r, 3)
expected := []struct {
weight int
opMsgRoute string
opMsgName string
}{
{simulation.WeightMsgCreateGroup, group.MsgCreateGroup{}.Route(), simulation.TypeMsgCreateGroup},
{simulation.WeightMsgCreateGroupPolicy, group.MsgCreateGroupPolicy{}.Route(), simulation.TypeMsgCreateGroupPolicy},
{simulation.WeightMsgCreateProposal, group.MsgCreateProposal{}.Route(), simulation.TypeMsgCreateProposal},
{simulation.WeightMsgVote, group.MsgVote{}.Route(), simulation.TypeMsgVote},
{simulation.WeightMsgExec, group.MsgExec{}.Route(), simulation.TypeMsgExec},
{simulation.WeightMsgUpdateGroupMetadata, group.MsgUpdateGroupMetadata{}.Route(), simulation.TypeMsgUpdateGroupMetadata},
{simulation.WeightMsgUpdateGroupAdmin, group.MsgUpdateGroupAdmin{}.Route(), simulation.TypeMsgUpdateGroupAdmin},
{simulation.WeightMsgUpdateGroupMembers, group.MsgUpdateGroupMembers{}.Route(), simulation.TypeMsgUpdateGroupMembers},
{simulation.WeightMsgUpdateGroupPolicyAdmin, group.MsgUpdateGroupPolicyAdmin{}.Route(), simulation.TypeMsgUpdateGroupPolicyAdmin},
{simulation.WeightMsgUpdateGroupPolicyDecisionPolicy, group.MsgUpdateGroupPolicyDecisionPolicy{}.Route(), simulation.TypeMsgUpdateGroupPolicyDecisionPolicy},
{simulation.WeightMsgUpdateGroupPolicyMetadata, group.MsgUpdateGroupPolicyMetadata{}.Route(), simulation.TypeMsgUpdateGroupPolicyMetadata},
}
for i, w := range weightedOps {
operationMsg, _, _ := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "")
// the following checks are very much dependent from the ordering of the output given
// by WeightedOperations. if the ordering in WeightedOperations changes some tests
// will fail
// fmt.Printf("%v %v\n", operationMsg, w.Weight())
suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same")
suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same")
suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same")
}
}
func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account {
accounts := simtypes.RandomAccounts(r, n)
initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction)
initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt))
// add coins to the accounts
for _, account := range accounts {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address)
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins))
}
return accounts
}
func (suite *SimTestSuite) TestSimulateCreateGroup() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 1)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
acc := accounts[0]
// execute operation
op := simulation.SimulateMsgCreateGroup(suite.app.AccountKeeper, suite.app.BankKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgCreateGroup
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(acc.Address.String(), msg.Admin)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateCreateGroupPolicy() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 1)
acc := accounts[0]
// setup a group
_, err := suite.app.GroupKeeper.CreateGroup(sdk.WrapSDKContext(suite.ctx),
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgCreateGroupPolicy(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgCreateGroupPolicy
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(acc.Address.String(), msg.Admin)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateCreateProposal() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 1)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: acc.Address.String(),
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgCreateProposal(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgCreateProposal
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(groupPolicyRes.Address, msg.Address)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateVote() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 1)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
addr := acc.Address.String()
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: addr,
Members: []group.Member{
{
Address: addr,
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: addr,
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// setup a proposal
proposalReq, err := group.NewMsgCreateProposalRequest(groupPolicyRes.Address, []string{addr}, []sdk.Msg{
&banktypes.MsgSend{
FromAddress: groupPolicyRes.Address,
ToAddress: addr,
Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)},
},
}, []byte{}, 0)
suite.Require().NoError(err)
_, err = suite.app.GroupKeeper.CreateProposal(ctx, proposalReq)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgVote(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgVote
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(addr, msg.Voter)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateExec() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 1)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
addr := acc.Address.String()
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: addr,
Members: []group.Member{
{
Address: addr,
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: addr,
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// setup a proposal
proposalReq, err := group.NewMsgCreateProposalRequest(groupPolicyRes.Address, []string{addr}, []sdk.Msg{
&banktypes.MsgSend{
FromAddress: groupPolicyRes.Address,
ToAddress: addr,
Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)},
},
}, []byte{}, 0)
suite.Require().NoError(err)
proposalRes, err := suite.app.GroupKeeper.CreateProposal(ctx, proposalReq)
suite.Require().NoError(err)
// vote
_, err = suite.app.GroupKeeper.Vote(ctx, &group.MsgVote{
ProposalId: proposalRes.ProposalId,
Voter: addr,
Choice: group.Choice_CHOICE_YES,
})
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgExec(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgExec
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(addr, msg.Signer)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupAdmin() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
_, err := suite.app.GroupKeeper.CreateGroup(sdk.WrapSDKContext(suite.ctx),
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupAdmin(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupAdmin
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(acc.Address.String(), msg.Admin)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupMetadata() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
_, err := suite.app.GroupKeeper.CreateGroup(sdk.WrapSDKContext(suite.ctx),
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupMetadata(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupMetadata
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(acc.Address.String(), msg.Admin)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupMembers() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
_, err := suite.app.GroupKeeper.CreateGroup(sdk.WrapSDKContext(suite.ctx),
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupMembers(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupMembers
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(acc.Address.String(), msg.Admin)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyAdmin() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: acc.Address.String(),
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupPolicyAdmin(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupPolicyAdmin
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(groupPolicyRes.Address, msg.Address)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyDecisionPolicy() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: acc.Address.String(),
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupPolicyDecisionPolicy(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupPolicyDecisionPolicy
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(groupPolicyRes.Address, msg.Address)
suite.Require().Len(futureOperations, 0)
}
func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyMetadata() {
// setup 1 account
s := rand.NewSource(1)
r := rand.New(s)
accounts := suite.getTestingAccounts(r, 2)
acc := accounts[0]
// setup a group
ctx := sdk.WrapSDKContext(suite.ctx)
groupRes, err := suite.app.GroupKeeper.CreateGroup(ctx,
&group.MsgCreateGroup{
Admin: acc.Address.String(),
Members: []group.Member{
{
Address: acc.Address.String(),
Weight: "1",
},
},
},
)
suite.Require().NoError(err)
// setup a group account
accountReq := &group.MsgCreateGroupPolicy{
Admin: acc.Address.String(),
GroupId: groupRes.GroupId,
Metadata: nil,
}
err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour))
suite.Require().NoError(err)
groupPolicyRes, err := suite.app.GroupKeeper.CreateGroupPolicy(ctx, accountReq)
suite.Require().NoError(err)
// begin a new block
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: suite.app.LastBlockHeight() + 1,
AppHash: suite.app.LastCommitID().Hash,
},
})
// execute operation
op := simulation.SimulateMsgUpdateGroupPolicyMetadata(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.GroupKeeper)
operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "")
suite.Require().NoError(err)
var msg group.MsgUpdateGroupPolicyMetadata
err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
suite.Require().NoError(err)
suite.Require().True(operationMsg.OK)
suite.Require().Equal(groupPolicyRes.Address, msg.Address)
suite.Require().Len(futureOperations, 0)
}
func TestSimTestSuite(t *testing.T) {
suite.Run(t, new(SimTestSuite))
}