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:
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
Reference in New Issue
Block a user