fix: add simulation tests for new param change (#14728)

This commit is contained in:
Julien Robert 2023-01-27 21:44:39 +01:00 committed by GitHub
parent 1ad8e86d1d
commit d3c3194185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 934 additions and 713 deletions

View File

@ -168,10 +168,11 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking Changes
* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
* (x/upgrade) [14764](https://github.com/cosmos/cosmos-sdk/pull/14764) The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module.
* (x/gov) [#14782](https://github.com/cosmos/cosmos-sdk/pull/14782) Move the `metadata` argument in `govv1.NewProposal` alongside `title` and `summary`.
* (store) [#14746](https://github.com/cosmos/cosmos-sdk/pull/14746) Extract Store in its own go.mod and rename the package to `cosmossdk.io/store`.
* (x/simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
* (simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
* (crypto/keyring) [#13734](https://github.com/cosmos/cosmos-sdk/pull/13834) The keyring's `Sign` method now takes a new `signMode` argument. It is only used if the signing key is a Ledger hardware device. You can set it to 0 in all other cases.
* (x/evidence) [14724](https://github.com/cosmos/cosmos-sdk/pull/14724) Extract Evidence in its own go.mod and rename the package to `cosmossdk.io/x/evidence`.
* (x/nft) [#14725](https://github.com/cosmos/cosmos-sdk/pull/14725) Extract NFT in its own go.mod and rename the package to `cosmossdk.io/x/nft`.

View File

@ -101,6 +101,10 @@ All the upgrade imports are now renamed to use `cosmossdk.io/x/upgrade` instead
Remove `RandomizedParams` from `AppModuleSimulation` interface. Previously, it used to generate random parameter changes during simulations, however, it does so through ParamChangeProposal which is now legacy. Since all modules were migrated, we can now safely remove this from `AppModuleSimulation` interface.
Moreover, to support the `MsgUpdateParams` governance proposals for each modules, `AppModuleSimulation` now defines a `AppModule.ProposalMsgs` method in addition to `AppModule.ProposalContents`. That method defines the messages that can be used to submit a proposal and that should be tested in simulation.
When a module has no proposal messages or proposal content to be tested by simulation, the `AppModule.ProposalMsgs` and `AppModule.ProposalContents` methods can be deleted.
### gRPC
A new gRPC service, `proto/cosmos/base/node/v1beta1/query.proto`, has been introduced

View File

@ -68,7 +68,8 @@ func SimulationOperations(app runtime.AppI, cdc codec.JSONCodec, config simtypes
}
}
simState.Contents = app.SimulationManager().GetProposalContents(simState)
simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck
simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState)
return app.SimulationManager().WeightedOperations(simState)
}

View File

@ -17,9 +17,6 @@ type AppModuleSimulation interface {
// randomized genesis states
GenerateGenesisState(input *SimulationState)
// content functions used to simulate governance proposals
ProposalContents(simState SimulationState) []simulation.WeightedProposalContent
// register a func to decode the each module's defined types from their corresponding store key
RegisterStoreDecoder(simulation.StoreDecoderRegistry)
@ -27,6 +24,18 @@ type AppModuleSimulation interface {
WeightedOperations(simState SimulationState) []simulation.WeightedOperation
}
// HasProposalMsgs defines the messages that can be used to simulate governance (v1) proposals
type HasProposalMsgs interface {
// msg functions used to simulate governance proposals
ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg
}
// HasProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals
type HasProposalContents interface {
// content functions used to simulate governance proposals
ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck
}
// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
type SimulationManager struct {
@ -76,12 +85,28 @@ func NewSimulationManagerFromAppModules(modules map[string]interface{}, override
return NewSimulationManager(simModules...)
}
// Deprecated: Use GetProposalMsgs instead.
// GetProposalContents returns each module's proposal content generator function
// with their default operation weight and key.
func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
for _, module := range sm.Modules {
wContents = append(wContents, module.ProposalContents(simState)...)
if module, ok := module.(HasProposalContents); ok {
wContents = append(wContents, module.ProposalContents(simState)...)
}
}
return wContents
}
// GetProposalMsgs returns each module's proposal msg generator function
// with their default operation weight and key.
func (sm *SimulationManager) GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg {
wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules))
for _, module := range sm.Modules {
if module, ok := module.(HasProposalMsgs); ok {
wContents = append(wContents, module.ProposalMsgs(simState)...)
}
}
return wContents
@ -115,16 +140,18 @@ func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simu
// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
BondDenom string // denom to be used as default
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
ParamChanges []simulation.ParamChange // simulated parameter changes from modules
Contents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
BondDenom string // denom to be used as default
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
//nolint:staticcheck
LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
ProposalMsgs []simulation.WeightedProposalMsg // proposal msg generator functions with their default weight and app sim key
}

View File

@ -12,14 +12,17 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
)
// Deprecated: Use WeightedProposalMsg instead.
type WeightedProposalContent interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
DefaultWeight() int // default weight
ContentSimulatorFn() ContentSimulatorFn // content simulator function
}
// Deprecated: Use MsgSimulatorFn instead.
type ContentSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) Content
// Deprecated: Use MsgSimulatorFn instead.
type Content interface {
GetTitle() string
GetDescription() string
@ -29,9 +32,17 @@ type Content interface {
String() string
}
type WeightedProposalMsg interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
DefaultWeight() int // default weight
MsgSimulatorFn() MsgSimulatorFn // msg simulator function
}
type MsgSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) sdk.Msg
type SimValFn func(r *rand.Rand) string
type ParamChange interface {
type LegacyParamChange interface {
Subspace() string
Key() string
SimValue() SimValFn

View File

@ -179,9 +179,9 @@ func (am AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState, am.randGenAccountsFn)
}
// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for auth module's types

View File

@ -1,38 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyMaxMemoCharacters = "MaxMemoCharacters"
keyTxSigLimit = "TxSigLimit"
keyTxSizeCostPerByte = "TxSizeCostPerByte"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyMaxMemoCharacters,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenMaxMemoChars(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTxSigLimit,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenTxSigLimit(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTxSizeCostPerByte,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenTxSizeCostPerByte(r))
},
),
}
}

View File

@ -1,37 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/auth/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"auth/MaxMemoCharacters", "MaxMemoCharacters", "\"181\"", "auth"},
{"auth/TxSigLimit", "TxSigLimit", "\"7\"", "auth"},
{"auth/TxSizeCostPerByte", "TxSizeCostPerByte", "\"12\"", "auth"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 3)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,47 @@
package simulation
import (
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 100
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.MaxMemoCharacters = uint64(simtypes.RandIntBetween(r, 1, 1000))
params.TxSigLimit = uint64(simtypes.RandIntBetween(r, 1, 1000))
params.TxSizeCostPerByte = uint64(simtypes.RandIntBetween(r, 1, 1000))
params.SigVerifyCostED25519 = uint64(simtypes.RandIntBetween(r, 1, 1000))
params.SigVerifyCostSecp256k1 = uint64(simtypes.RandIntBetween(r, 1, 1000))
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,45 @@
package simulation_test
import (
"math/rand"
"testing"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.Equal(t, uint64(999), msgUpdateParams.Params.MaxMemoCharacters)
assert.Equal(t, uint64(905), msgUpdateParams.Params.TxSigLimit)
assert.Equal(t, uint64(151), msgUpdateParams.Params.TxSizeCostPerByte)
assert.Equal(t, uint64(213), msgUpdateParams.Params.SigVerifyCostED25519)
assert.Equal(t, uint64(539), msgUpdateParams.Params.SigVerifyCostSecp256k1)
}

View File

@ -207,12 +207,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents returns all the authz content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder registers a decoder for authz module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc)

View File

@ -3,6 +3,7 @@ package authz
import (
"time"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec"
"github.com/cosmos/gogoproto/proto"
@ -10,7 +11,6 @@ import (
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
)
var (

View File

@ -26,12 +26,10 @@ var (
)
// Simulation operation weights constants
//
//nolint:gosec // these are not hardcoded credentials.
const (
OpWeightMsgGrant = "op_weight_msg_grant"
OpWeightRevoke = "op_weight_msg_revoke"
OpWeightExec = "op_weight_msg_execute"
OpWeightMsgGrant = "op_weight_msg_grant" //nolint:gosec
OpWeightRevoke = "op_weight_msg_revoke" //nolint:gosec
OpWeightExec = "op_weight_msg_execute" //nolint:gosec
)
// authz operations weights

View File

@ -183,9 +183,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for supply module's types

View File

@ -17,13 +17,11 @@ import (
)
// Simulation operation weights constants
//
//nolint:gosec // these are not hardcoded credentials.
const (
OpWeightMsgSend = "op_weight_msg_send"
OpWeightMsgMultiSend = "op_weight_msg_multisend"
DefaultWeightMsgSend = 100 // from simappparams.DefaultWeightMsgSend
DefaultWeightMsgMultiSend = 10 // from simappparams.DefaultWeightMsgMultiSend
OpWeightMsgSend = "op_weight_msg_send" //nolint:gosec
OpWeightMsgMultiSend = "op_weight_msg_multisend" //nolint:gosec
DefaultWeightMsgSend = 100 // from simappparams.DefaultWeightMsgSend
DefaultWeightMsgMultiSend = 10 // from simappparams.DefaultWeightMsgMultiSend
)
// WeightedOperations returns all the operations from the module with their respective weights

View File

@ -1,23 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/simulation"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, string(types.KeyDefaultSendEnabled),
func(r *rand.Rand) string {
return fmt.Sprintf("%v", RandomGenesisDefaultSendEnabledParam(r))
},
),
}
}

View File

@ -1,35 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/bank/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"bank/DefaultSendEnabled", "DefaultSendEnabled", "true", "bank"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, len(expected))
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,43 @@
package simulation
import (
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 100
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.DefaultSendEnabled = r.Intn(2) == 0
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,44 @@
package simulation_test
import (
"fmt"
"math/rand"
"testing"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
fmt.Println(msgUpdateParams)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.Assert(t, len(msgUpdateParams.Params.SendEnabled) == 0) //nolint:staticcheck
assert.Equal(t, true, msgUpdateParams.Params.DefaultSendEnabled)
}

View File

@ -163,11 +163,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents performs a no-op
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder registers a decoder for capability module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc)

View File

@ -185,10 +185,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents returns all the distribution content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for distribution module's types

View File

@ -18,13 +18,11 @@ import (
)
// Simulation operation weights constants
//
//nolint:gosec // these are not hardcoded credentials.
const (
OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address"
OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward"
OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission"
OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool"
OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address" //nolint:gosec
OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward" //nolint:gosec
OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission" //nolint:gosec
OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool" //nolint:gosec
DefaultWeightMsgSetWithdrawAddress int = 50
DefaultWeightMsgWithdrawDelegationReward int = 50

View File

@ -1,27 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/simulation"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
const (
keyCommunityTax = "communitytax"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyCommunityTax,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenCommunityTax(r))
},
),
}
}

View File

@ -1,35 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/distribution/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"distribution/communitytax", "communitytax", "\"0.120000000000000000\"", "distribution"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 1)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,44 @@
package simulation
import (
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 50
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.CommunityTax = simtypes.RandomDecAmount(r, sdk.NewDec(1))
params.WithdrawAddrEnabled = r.Intn(2) == 0
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,42 @@
package simulation_test
import (
"math/rand"
"testing"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.DeepEqual(t, sdk.NewDec(0), msgUpdateParams.Params.CommunityTax)
assert.Equal(t, true, msgUpdateParams.Params.WithdrawAddrEnabled)
}

View File

@ -177,12 +177,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents returns all the evidence content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder registers a decoder for evidence module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper)

View File

@ -208,12 +208,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents returns all the feegrant content functions used to
// simulate governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder registers a decoder for feegrant module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc)

View File

@ -334,10 +334,15 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
// ProposalContents returns all the gov content functions used to
// simulate governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { //nolint:staticcheck
return simulation.ProposalContents()
}
// ProposalMsgs returns all the gov msgs used to simulate governance proposals.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for gov module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[govtypes.StoreKey] = simulation.NewDecodeStore(am.cdc)
@ -347,6 +352,7 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
return simulation.WeightedOperations(
simState.AppParams, simState.Cdc,
am.accountKeeper, am.bankKeeper, am.keeper, simState.Contents,
am.accountKeeper, am.bankKeeper, am.keeper,
simState.ProposalMsgs, simState.LegacyProposalContents,
)
}

View File

@ -26,6 +26,7 @@ var (
TypeMsgVoteWeighted = sdk.MsgTypeURL(&v1.MsgVoteWeighted{})
TypeMsgSubmitProposal = sdk.MsgTypeURL(&v1.MsgSubmitProposal{})
TypeMsgCancelProposal = sdk.MsgTypeURL(&v1.MsgCancelProposal{})
TypeMsgUpdateParams = sdk.MsgTypeURL(&v1.MsgUpdateParams{})
)
// Simulation operation weights constants
@ -45,7 +46,7 @@ const (
)
// WeightedOperations returns all the operations from the module with their respective weights
func WeightedOperations(appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper, wContents []simtypes.WeightedProposalContent) simulation.WeightedOperations {
func WeightedOperations(appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper, wMsgs []simtypes.WeightedProposalMsg, wContents []simtypes.WeightedProposalContent) simulation.WeightedOperations { //nolint:staticcheck
var (
weightMsgDeposit int
weightMsgVote int
@ -77,20 +78,36 @@ func WeightedOperations(appParams simtypes.AppParams, cdc codec.JSONCodec, ak ty
},
)
// generate the weighted operations for the proposal contents
// generate the weighted operations for the proposal msgs
var wProposalOps simulation.WeightedOperations
for _, wMsg := range wMsgs {
wMsg := wMsg // pin variable
var weight int
appParams.GetOrGenerate(cdc, wMsg.AppParamsKey(), &weight, nil,
func(_ *rand.Rand) { weight = wMsg.DefaultWeight() })
wProposalOps = append(
wProposalOps,
simulation.NewWeightedOperation(
weight,
SimulateMsgSubmitProposal(ak, bk, k, wMsg.MsgSimulatorFn()),
),
)
}
// generate the weighted operations for the proposal contents
var wLegacyProposalOps simulation.WeightedOperations
for _, wContent := range wContents {
wContent := wContent // pin variable
var weight int
appParams.GetOrGenerate(cdc, wContent.AppParamsKey(), &weight, nil,
func(_ *rand.Rand) { weight = wContent.DefaultWeight() })
wProposalOps = append(
wProposalOps,
wLegacyProposalOps = append(
wLegacyProposalOps,
simulation.NewWeightedOperation(
weight,
SimulateMsgSubmitProposal(ak, bk, k, wContent.ContentSimulatorFn()),
SimulateMsgSubmitLegacyProposal(ak, bk, k, wContent.ContentSimulatorFn()),
),
)
}
@ -114,34 +131,43 @@ func WeightedOperations(appParams simtypes.AppParams, cdc codec.JSONCodec, ak ty
),
}
return append(wProposalOps, wGovOps...)
return append(wGovOps, append(wProposalOps, wLegacyProposalOps...)...)
}
// SimulateMsgSubmitProposal simulates creating a msg Submit Proposal
// voting on the proposal, and subsequently slashing the proposal. It is implemented using
// future operations.
func SimulateMsgSubmitProposal(ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper, contentSim simtypes.ContentSimulatorFn) simtypes.Operation {
// The states are:
// column 1: All validators vote
// column 2: 90% vote
// column 3: 75% vote
// column 4: 40% vote
// column 5: 15% vote
// column 6: noone votes
// All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily,
// feel free to change.
numVotesTransitionMatrix, _ := simulation.CreateTransitionMatrix([][]int{
{20, 10, 0, 0, 0, 0},
{55, 50, 20, 10, 0, 0},
{25, 25, 30, 25, 30, 15},
{0, 15, 30, 25, 30, 30},
{0, 0, 20, 30, 30, 30},
{0, 0, 0, 10, 10, 25},
})
func SimulateMsgSubmitProposal(ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper, msgSim simtypes.MsgSimulatorFn) simtypes.Operation {
return func(
r *rand.Rand,
app *baseapp.BaseApp,
ctx sdk.Context,
accs []simtypes.Account,
chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
simAccount, _ := simtypes.RandomAcc(r, accs)
deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, true)
switch {
case skip:
return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "skip deposit"), nil, nil
case err != nil:
return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "unable to generate deposit"), nil, err
}
statePercentageArray := []float64{1, .9, .75, .4, .15, 0}
curNumVotesState := 1
msgs := []sdk.Msg{}
proposalMsg := msgSim(r, ctx, accs)
if proposalMsg != nil {
msgs = append(msgs, proposalMsg)
}
return simulateMsgSubmitProposal(ak, bk, k, msgs, simAccount, deposit)(r, app, ctx, accs, chainID)
}
}
// SimulateMsgSubmitLegacyProposal simulates creating a msg Submit Proposal
// voting on the proposal, and subsequently slashing the proposal. It is implemented using
// future operations.
func SimulateMsgSubmitLegacyProposal(ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper, contentSim simtypes.ContentSimulatorFn) simtypes.Operation { //nolint:staticcheck
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simtypes.Account, chainID string,
@ -167,7 +193,54 @@ func SimulateMsgSubmitProposal(ak types.AccountKeeper, bk types.BankKeeper, k *k
return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error converting legacy content into proposal message"), nil, err
}
msg, err := v1.NewMsgSubmitProposal([]sdk.Msg{contentMsg}, deposit, simAccount.Address.String(), "", "Title of proposal", "Short description of proposal")
return simulateMsgSubmitProposal(ak, bk, k, []sdk.Msg{contentMsg}, simAccount, deposit)(r, app, ctx, accs, chainID)
}
}
func simulateMsgSubmitProposal(
ak types.AccountKeeper,
bk types.BankKeeper,
k *keeper.Keeper,
proposalMsgs []sdk.Msg,
simAccount simtypes.Account,
deposit sdk.Coins,
) simtypes.Operation {
// The states are:
// column 1: All validators vote
// column 2: 90% vote
// column 3: 75% vote
// column 4: 40% vote
// column 5: 15% vote
// column 6: noone votes
// All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily,
// feel free to change.
numVotesTransitionMatrix, _ := simulation.CreateTransitionMatrix([][]int{
{20, 10, 0, 0, 0, 0},
{55, 50, 20, 10, 0, 0},
{25, 25, 30, 25, 30, 15},
{0, 15, 30, 25, 30, 30},
{0, 0, 20, 30, 30, 30},
{0, 0, 0, 10, 10, 25},
})
statePercentageArray := []float64{1, .9, .75, .4, .15, 0}
curNumVotesState := 1
return func(
r *rand.Rand,
app *baseapp.BaseApp,
ctx sdk.Context,
accs []simtypes.Account,
chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
msg, err := v1.NewMsgSubmitProposal(
proposalMsgs,
deposit,
simAccount.Address.String(),
simtypes.RandStringOfLength(r, 100),
simtypes.RandStringOfLength(r, 100),
simtypes.RandStringOfLength(r, 100),
)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate a submit proposal msg"), nil, err
}

View File

@ -6,11 +6,11 @@ import (
"testing"
"time"
storetypes "cosmossdk.io/store/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil/configurator"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
@ -36,20 +36,31 @@ import (
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
)
type MockWeightedProposalContent struct {
var (
_ simtypes.WeightedProposalMsg = MockWeightedProposals{}
_ simtypes.WeightedProposalContent = MockWeightedProposals{} //nolint:staticcheck
)
type MockWeightedProposals struct {
n int
}
func (m MockWeightedProposalContent) AppParamsKey() string {
func (m MockWeightedProposals) AppParamsKey() string {
return fmt.Sprintf("AppParamsKey-%d", m.n)
}
func (m MockWeightedProposalContent) DefaultWeight() int {
func (m MockWeightedProposals) DefaultWeight() int {
return m.n
}
func (m MockWeightedProposalContent) ContentSimulatorFn() simtypes.ContentSimulatorFn {
return func(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content {
func (m MockWeightedProposals) MsgSimulatorFn() simtypes.MsgSimulatorFn {
return func(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
return nil
}
}
func (m MockWeightedProposals) ContentSimulatorFn() simtypes.ContentSimulatorFn { //nolint:staticcheck
return func(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content { //nolint:staticcheck
return v1beta1.NewTextProposal(
fmt.Sprintf("title-%d: %s", m.n, simtypes.RandStringOfLength(r, 100)),
fmt.Sprintf("description-%d: %s", m.n, simtypes.RandStringOfLength(r, 4000)),
@ -57,13 +68,18 @@ func (m MockWeightedProposalContent) ContentSimulatorFn() simtypes.ContentSimula
}
}
// make sure the MockWeightedProposalContent satisfied the WeightedProposalContent interface
var _ simtypes.WeightedProposalContent = MockWeightedProposalContent{}
func mockWeightedProposalContent(n int) []simtypes.WeightedProposalContent {
wpc := make([]simtypes.WeightedProposalContent, n)
func mockWeightedProposalMsg(n int) []simtypes.WeightedProposalMsg {
wpc := make([]simtypes.WeightedProposalMsg, n)
for i := 0; i < n; i++ {
wpc[i] = MockWeightedProposalContent{i}
wpc[i] = MockWeightedProposals{i}
}
return wpc
}
func mockWeightedLegacyProposalContent(n int) []simtypes.WeightedProposalContent { //nolint:staticcheck
wpc := make([]simtypes.WeightedProposalContent, n) //nolint:staticcheck
for i := 0; i < n; i++ {
wpc[i] = MockWeightedProposals{i}
}
return wpc
}
@ -73,12 +89,10 @@ func TestWeightedOperations(t *testing.T) {
suite, ctx := createTestSuite(t, false)
app := suite.App
ctx.WithChainID("test-chain")
cdc := suite.cdc
appParams := make(simtypes.AppParams)
weightesOps := simulation.WeightedOperations(appParams, cdc, suite.AccountKeeper,
suite.BankKeeper, suite.GovKeeper, mockWeightedProposalContent(3),
weightesOps := simulation.WeightedOperations(appParams, govcodec.ModuleCdc, suite.AccountKeeper,
suite.BankKeeper, suite.GovKeeper, mockWeightedProposalMsg(3), mockWeightedLegacyProposalContent(1),
)
// setup 3 accounts
@ -91,18 +105,19 @@ func TestWeightedOperations(t *testing.T) {
opMsgRoute string
opMsgName string
}{
{0, types.ModuleName, simulation.TypeMsgSubmitProposal},
{1, types.ModuleName, simulation.TypeMsgSubmitProposal},
{2, types.ModuleName, simulation.TypeMsgSubmitProposal},
{simulation.DefaultWeightMsgDeposit, types.ModuleName, simulation.TypeMsgDeposit},
{simulation.DefaultWeightMsgVote, types.ModuleName, simulation.TypeMsgVote},
{simulation.DefaultWeightMsgVoteWeighted, types.ModuleName, simulation.TypeMsgVoteWeighted},
{simulation.DefaultWeightMsgCancelProposal, types.ModuleName, simulation.TypeMsgCancelProposal},
{0, types.ModuleName, simulation.TypeMsgSubmitProposal},
{1, types.ModuleName, simulation.TypeMsgSubmitProposal},
{2, types.ModuleName, simulation.TypeMsgSubmitProposal},
{0, types.ModuleName, simulation.TypeMsgSubmitProposal},
}
for i, w := range weightesOps {
operationMsg, _, _ := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID())
// require.NoError(t, err) // TODO check if it should be NoError
operationMsg, _, err := w.Op()(r, app.BaseApp, ctx.WithBlockGasMeter(storetypes.NewInfiniteGasMeter()), accs, ctx.ChainID())
require.NoError(t, err)
// the following checks are very much dependent from the ordering of the output given
// by WeightedOperations. if the ordering in WeightedOperations changes some tests
@ -128,7 +143,37 @@ func TestSimulateMsgSubmitProposal(t *testing.T) {
app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash}})
// execute operation
op := simulation.SimulateMsgSubmitProposal(suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposalContent{3}.ContentSimulatorFn())
op := simulation.SimulateMsgSubmitProposal(suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.MsgSimulatorFn())
operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "")
require.NoError(t, err)
var msg v1.MsgSubmitProposal
err = govcodec.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg)
require.NoError(t, err)
require.True(t, operationMsg.OK)
require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Proposer)
require.NotEqual(t, len(msg.InitialDeposit), 0)
require.Equal(t, "560969stake", msg.InitialDeposit[0].String())
require.Equal(t, simulation.TypeMsgSubmitProposal, sdk.MsgTypeURL(&msg))
}
// TestSimulateMsgSubmitProposal tests the normal scenario of a valid message of type TypeMsgSubmitProposal.
// Abnormal scenarios, where errors occur, are not tested here.
func TestSimulateMsgSubmitLegacyProposal(t *testing.T) {
suite, ctx := createTestSuite(t, false)
app := suite.App
// setup 3 accounts
s := rand.NewSource(1)
r := rand.New(s)
accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3)
// begin a new block
app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash}})
// execute operation
op := simulation.SimulateMsgSubmitLegacyProposal(suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.ContentSimulatorFn())
operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "")
require.NoError(t, err)
@ -323,7 +368,6 @@ func TestSimulateMsgVoteWeighted(t *testing.T) {
}
type suite struct {
cdc codec.Codec
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
GovKeeper *keeper.Keeper
@ -345,7 +389,7 @@ func createTestSuite(t *testing.T, isCheckTx bool) (suite, sdk.Context) {
configurator.ConsensusModule(),
configurator.DistributionModule(),
configurator.GovModule(),
), &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, &res.DistributionKeeper, &res.cdc)
), &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, &res.DistributionKeeper)
require.NoError(t, err)
ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})

View File

@ -1,67 +0,0 @@
package simulation
import (
"encoding/json"
"fmt"
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
const (
keyVotingParams = "votingparams"
keyDepositParams = "depositparams"
keyTallyParams = "tallyparams"
subkeyQuorum = "quorum"
subkeyThreshold = "threshold"
subkeyVeto = "veto"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyVotingParams,
func(r *rand.Rand) string {
return fmt.Sprintf(`{"voting_period": "%d"}`, GenVotingParamsVotingPeriod(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyDepositParams,
func(r *rand.Rand) string {
return fmt.Sprintf(`{"max_deposit_period": "%d"}`, GenDepositParamsDepositPeriod(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyTallyParams,
func(r *rand.Rand) string {
changes := []struct {
key string
value sdk.Dec
}{
{subkeyQuorum, GenTallyParamsQuorum(r)},
{subkeyThreshold, GenTallyParamsThreshold(r)},
{subkeyVeto, GenTallyParamsVeto(r)},
}
pc := make(map[string]string)
numChanges := simtypes.RandIntBetween(r, 1, len(changes))
for i := 0; i < numChanges; i++ {
c := changes[r.Intn(len(changes))]
_, ok := pc[c.key]
for ok {
c := changes[r.Intn(len(changes))]
_, ok = pc[c.key]
}
pc[c.key] = c.value.String()
}
bz, _ := json.Marshal(pc)
return string(bz)
},
),
}
}

View File

@ -1,37 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/gov/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"gov/votingparams", "votingparams", "{\"voting_period\": \"82639000000000\"}", "gov"},
{"gov/depositparams", "depositparams", "{\"max_deposit_period\": \"47332000000000\"}", "gov"},
{"gov/tallyparams", "tallyparams", "{\"threshold\":\"0.509000000000000000\"}", "gov"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 3)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -12,19 +12,40 @@ import (
// OpWeightSubmitTextProposal app params key for text proposal
const OpWeightSubmitTextProposal = "op_weight_submit_text_proposal"
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightSubmitTextProposal,
DefaultWeightTextProposal,
SimulateTextProposal,
),
}
}
// SimulateTextProposal returns a random text proposal content.
// A text proposal is a proposal that contains no msgs.
func SimulateTextProposal(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
return nil
}
// ProposalContents defines the module weighted proposals' contents
//
//nolint:staticcheck
func ProposalContents() []simtypes.WeightedProposalContent {
return []simtypes.WeightedProposalContent{
simulation.NewWeightedProposalContent(
OpWeightMsgDeposit,
DefaultWeightTextProposal,
SimulateTextProposalContent,
SimulateLegacyTextProposalContent,
),
}
}
// SimulateTextProposalContent returns a random text proposal content.
func SimulateTextProposalContent(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content {
//
//nolint:staticcheck
func SimulateLegacyTextProposalContent(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content {
return v1beta1.NewTextProposal(
simtypes.RandStringOfLength(r, 140),
simtypes.RandStringOfLength(r, 5000),

File diff suppressed because one or more lines are too long

View File

@ -173,12 +173,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents returns all the group content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder registers a decoder for group module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[group.StoreKey] = simulation.NewDecodeStore(am.cdc)

View File

@ -191,9 +191,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for mint module's types.

View File

@ -1,45 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
"github.com/cosmos/cosmos-sdk/x/simulation"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/mint/types"
)
const (
keyInflationRateChange = "InflationRateChange"
keyInflationMax = "InflationMax"
keyInflationMin = "InflationMin"
keyGoalBonded = "GoalBonded"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keyInflationRateChange,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationRateChange(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyInflationMax,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationMax(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyInflationMin,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenInflationMin(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyGoalBonded,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenGoalBonded(r))
},
),
}
}

View File

@ -1,37 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/mint/simulation"
)
func TestParamChangest(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"mint/InflationRateChange", "InflationRateChange", "\"0.230000000000000000\"", "mint"},
{"mint/InflationMax", "InflationMax", "\"0.200000000000000000\"", "mint"},
{"mint/InflationMin", "InflationMin", "\"0.070000000000000000\"", "mint"},
{"mint/GoalBonded", "GoalBonded", "\"0.670000000000000000\"", "mint"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 4)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,48 @@
package simulation
import (
"math/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 100
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.BlocksPerYear = uint64(simtypes.RandIntBetween(r, 1, 1000000))
params.GoalBonded = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 100)), 2)
params.InflationMin = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 50)), 2)
params.InflationMax = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 50, 100)), 2)
params.InflationRateChange = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 100)), 2)
params.MintDenom = simtypes.RandStringOfLength(r, 10)
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,46 @@
package simulation_test
import (
"math/rand"
"testing"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/mint/simulation"
"github.com/cosmos/cosmos-sdk/x/mint/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.Equal(t, uint64(122877), msgUpdateParams.Params.BlocksPerYear)
assert.DeepEqual(t, sdk.NewDecWithPrec(95, 2), msgUpdateParams.Params.GoalBonded)
assert.DeepEqual(t, sdk.NewDecWithPrec(94, 2), msgUpdateParams.Params.InflationMax)
assert.DeepEqual(t, sdk.NewDecWithPrec(23, 2), msgUpdateParams.Params.InflationMin)
assert.DeepEqual(t, sdk.NewDecWithPrec(89, 2), msgUpdateParams.Params.InflationRateChange)
assert.Equal(t, "XhhuTSkuxK", msgUpdateParams.Params.MintDenom)
}

View File

@ -16,13 +16,10 @@ import (
"cosmossdk.io/x/nft/keeper"
)
//nolint:gosec // these are not hardcoded credentials.
const (
// OpWeightMsgSend Simulation operation weights constants
OpWeightMsgSend = "op_weight_msg_send"
)
OpWeightMsgSend = "op_weight_msg_send" //nolint:gosec
const (
// WeightSend nft operations weights
WeightSend = 100
)

View File

@ -114,12 +114,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
proposal.RegisterQueryServer(cfg.QueryServer(), am.keeper)
}
// ProposalContents returns all the params content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}
// RegisterStoreDecoder doesn't register any type.
func (AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {}

View File

@ -19,7 +19,7 @@ func min(a int, b int) int {
// SimulateParamChangeProposalContent returns random parameter change content.
// It will generate a ParameterChangeProposal object with anywhere between 1 and
// the total amount of defined parameters changes, all of which have random valid values.
func SimulateParamChangeProposalContent(paramChangePool []simulation.ParamChange) simulation.ContentSimulatorFn {
func SimulateParamChangeProposalContent(paramChangePool []simulation.LegacyParamChange) simulation.ContentSimulatorFn { //nolint:staticcheck
numProposals := 0
// Bound the maximum number of simultaneous parameter changes
maxSimultaneousParamChanges := min(len(paramChangePool), 1000)
@ -27,7 +27,7 @@ func SimulateParamChangeProposalContent(paramChangePool []simulation.ParamChange
panic("param changes array is empty")
}
return func(r *rand.Rand, _ sdk.Context, _ []simulation.Account) simulation.Content {
return func(r *rand.Rand, _ sdk.Context, _ []simulation.Account) simulation.Content { //nolint:staticcheck
numChanges := simulation.RandIntBetween(r, 1, maxSimultaneousParamChanges)
paramChanges := make([]proposal.ParamChange, numChanges)

View File

@ -37,7 +37,7 @@ func (pc MockParamChange) SimValue() simtypes.SimValFn {
}
// make sure that the MockParamChange satisfied the ParamChange interface
var _ simtypes.ParamChange = MockParamChange{}
var _ simtypes.LegacyParamChange = MockParamChange{}
func TestSimulateParamChangeProposalContent(t *testing.T) {
s := rand.NewSource(1)
@ -45,7 +45,7 @@ func TestSimulateParamChangeProposalContent(t *testing.T) {
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
paramChangePool := []simtypes.ParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}}
paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}}
// execute operation
op := simulation.SimulateParamChangeProposalContent(paramChangePool)

View File

@ -12,7 +12,9 @@ const (
)
// ProposalContents defines the module weighted proposals' contents
func ProposalContents(paramChanges []simtypes.ParamChange) []simtypes.WeightedProposalContent {
//
//nolint:staticcheck
func ProposalContents(paramChanges []simtypes.LegacyParamChange) []simtypes.WeightedProposalContent {
return []simtypes.WeightedProposalContent{
simulation.NewWeightedProposalContent(
OpWeightSubmitParamChangeProposal,

View File

@ -21,7 +21,7 @@ func TestProposalContents(t *testing.T) {
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
paramChangePool := []simtypes.ParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}}
paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}}
// execute ProposalContents function
weightedProposalContent := simulation.ProposalContents(paramChangePool)

View File

@ -86,52 +86,78 @@ func RandomParams(r *rand.Rand) Params {
}
}
// Param change proposals
// Legacy param change proposals
// ParamChange defines the object used for simulating parameter change proposals
type ParamChange struct {
// LegacyParamChange defines the object used for simulating parameter change proposals
type LegacyParamChange struct {
subspace string
key string
simValue simulation.SimValFn
}
func (spc ParamChange) Subspace() string {
func (spc LegacyParamChange) Subspace() string {
return spc.subspace
}
func (spc ParamChange) Key() string {
func (spc LegacyParamChange) Key() string {
return spc.key
}
func (spc ParamChange) SimValue() simulation.SimValFn {
func (spc LegacyParamChange) SimValue() simulation.SimValFn {
return spc.simValue
}
// NewSimParamChange creates a new ParamChange instance
func NewSimParamChange(subspace, key string, simVal simulation.SimValFn) simulation.ParamChange {
return ParamChange{
// ComposedKey creates a new composed key for the legacy param change proposal
func (spc LegacyParamChange) ComposedKey() string {
return spc.Subspace() + "/" + spc.Key()
}
// NewSimLegacyParamChange creates a new LegacyParamChange instance
func NewSimLegacyParamChange(subspace, key string, simVal simulation.SimValFn) simulation.LegacyParamChange {
return LegacyParamChange{
subspace: subspace,
key: key,
simValue: simVal,
}
}
// ComposedKey creates a new composed key for the param change proposal
func (spc ParamChange) ComposedKey() string {
return spc.Subspace() + "/" + spc.Key()
// Proposal Msgs
// WeightedProposalMsg defines a common struct for proposal msgs defined by external modules (i.e outside gov)
type WeightedProposalMsg struct {
appParamsKey string // key used to retrieve the value of the weight from the simulation application params
defaultWeight int // default weight
msgSimulatorFn simulation.MsgSimulatorFn // msg simulator function
}
// Proposal Contents
func NewWeightedProposalMsg(appParamsKey string, defaultWeight int, msgSimulatorFn simulation.MsgSimulatorFn) simulation.WeightedProposalMsg {
return &WeightedProposalMsg{appParamsKey: appParamsKey, defaultWeight: defaultWeight, msgSimulatorFn: msgSimulatorFn}
}
// WeightedProposalContent defines a common struct for proposal contents defined by
// external modules (i.e outside gov)
func (w WeightedProposalMsg) AppParamsKey() string {
return w.appParamsKey
}
func (w WeightedProposalMsg) DefaultWeight() int {
return w.defaultWeight
}
func (w WeightedProposalMsg) MsgSimulatorFn() simulation.MsgSimulatorFn {
return w.msgSimulatorFn
}
// Legacy Proposal Content
// WeightedProposalContent defines a common struct for proposal content defined by external modules (i.e outside gov)
//
//nolint:staticcheck
type WeightedProposalContent struct {
appParamsKey string // key used to retrieve the value of the weight from the simulation application params
defaultWeight int // default weight
contentSimulatorFn simulation.ContentSimulatorFn // content simulator function
}
func NewWeightedProposalContent(appParamsKey string, defaultWeight int, contentSimulatorFn simulation.ContentSimulatorFn) simulation.WeightedProposalContent {
func NewWeightedProposalContent(appParamsKey string, defaultWeight int, contentSimulatorFn simulation.ContentSimulatorFn) simulation.WeightedProposalContent { //nolint:staticcheck
return &WeightedProposalContent{appParamsKey: appParamsKey, defaultWeight: defaultWeight, contentSimulatorFn: contentSimulatorFn}
}
@ -143,11 +169,11 @@ func (w WeightedProposalContent) DefaultWeight() int {
return w.defaultWeight
}
func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulatorFn {
func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulatorFn { //nolint:staticcheck
return w.contentSimulatorFn
}
// Param change proposals
// Consensus Params
// randomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state.
func randomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec) *tmproto.ConsensusParams {

View File

@ -12,13 +12,13 @@ import (
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
)
func TestParamChange(t *testing.T) {
func TestLegacyParamChange(t *testing.T) {
subspace, key := "theSubspace", "key"
f := func(r *rand.Rand) string {
return "theResult"
}
pChange := NewSimParamChange(subspace, key, f)
pChange := NewSimLegacyParamChange(subspace, key, f)
require.Equal(t, subspace, pChange.Subspace())
require.Equal(t, key, pChange.Key())
@ -30,7 +30,7 @@ func TestNewWeightedProposalContent(t *testing.T) {
key := "theKey"
weight := 1
content := &testContent{}
f := func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
f := func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content { //nolint:staticcheck
return content
}

View File

@ -182,9 +182,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for slashing module's types

View File

@ -18,10 +18,9 @@ import (
)
// Simulation operation weights constants
//
//nolint:gosec // these are not hardcoded credentials.
const (
OpWeightMsgUnjail = "op_weight_msg_unjail"
OpWeightMsgUnjail = "op_weight_msg_unjail" //nolint:gosec
DefaultWeightMsgUnjail = 100
)
@ -31,6 +30,7 @@ func WeightedOperations(
bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper,
) simulation.WeightedOperations {
interfaceRegistry := codectypes.NewInterfaceRegistry()
var weightMsgUnjail int
appParams.GetOrGenerate(cdc, OpWeightMsgUnjail, &weightMsgUnjail, nil,
func(_ *rand.Rand) {

View File

@ -1,38 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
const (
keySignedBlocksWindow = "SignedBlocksWindow"
keyMinSignedPerWindow = "MinSignedPerWindow"
keySlashFractionDowntime = "SlashFractionDowntime"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, keySignedBlocksWindow,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", GenSignedBlocksWindow(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keyMinSignedPerWindow,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenMinSignedPerWindow(r))
},
),
simulation.NewSimParamChange(types.ModuleName, keySlashFractionDowntime,
func(r *rand.Rand) string {
return fmt.Sprintf("\"%s\"", GenSlashFractionDowntime(r))
},
),
}
}

View File

@ -1,37 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/slashing/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"slashing/SignedBlocksWindow", "SignedBlocksWindow", "\"231\"", "slashing"},
{"slashing/MinSignedPerWindow", "MinSignedPerWindow", "\"0.700000000000000000\"", "slashing"},
{"slashing/SlashFractionDowntime", "SlashFractionDowntime", "\"0.020833333333333333\"", "slashing"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 3)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,48 @@
package simulation
import (
"math/rand"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 100
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.DowntimeJailDuration = time.Duration(simtypes.RandTimestamp(r).UnixNano())
params.SignedBlocksWindow = int64(simtypes.RandIntBetween(r, 1, 1000))
params.MinSignedPerWindow = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 100)), 2)
params.SlashFractionDoubleSign = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 100)), 2)
params.SlashFractionDowntime = sdk.NewDecWithPrec(int64(simtypes.RandIntBetween(r, 1, 100)), 2)
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,46 @@
package simulation_test
import (
"math/rand"
"testing"
"time"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.Equal(t, int64(905), msgUpdateParams.Params.SignedBlocksWindow)
assert.DeepEqual(t, sdk.NewDecWithPrec(7, 2), msgUpdateParams.Params.MinSignedPerWindow)
assert.DeepEqual(t, sdk.NewDecWithPrec(60, 2), msgUpdateParams.Params.SlashFractionDoubleSign)
assert.DeepEqual(t, sdk.NewDecWithPrec(89, 2), msgUpdateParams.Params.SlashFractionDowntime)
assert.Equal(t, 3313479009*time.Second, msgUpdateParams.Params.DowntimeJailDuration)
}

View File

@ -289,9 +289,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}
// RegisterStoreDecoder registers a decoder for staking module's types

View File

@ -1,32 +0,0 @@
package simulation
import (
"fmt"
"math/rand"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// ParamChanges defines the parameters that can be modified by param change proposals
// on the simulation
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, string(types.KeyMaxValidators),
func(r *rand.Rand) string {
return fmt.Sprintf("%d", genMaxValidators(r))
},
),
simulation.NewSimParamChange(types.ModuleName, string(types.KeyUnbondingTime),
func(r *rand.Rand) string {
return fmt.Sprintf("\"%d\"", genUnbondingTime(r))
},
),
simulation.NewSimParamChange(types.ModuleName, string(types.KeyHistoricalEntries),
func(r *rand.Rand) string {
return fmt.Sprintf("%d", getHistEntries(r))
},
),
}
}

View File

@ -1,37 +0,0 @@
package simulation_test
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/staking/simulation"
)
func TestParamChanges(t *testing.T) {
s := rand.NewSource(1)
r := rand.New(s)
expected := []struct {
composedKey string
key string
simValue string
subspace string
}{
{"staking/MaxValidators", "MaxValidators", "82", "staking"},
{"staking/UnbondingTime", "UnbondingTime", "\"275307000000000\"", "staking"},
{"staking/HistoricalEntries", "HistoricalEntries", "9149", "staking"},
}
paramChanges := simulation.ParamChanges(r)
require.Len(t, paramChanges, 3)
for i, p := range paramChanges {
require.Equal(t, expected[i].composedKey, p.ComposedKey())
require.Equal(t, expected[i].key, p.Key())
require.Equal(t, expected[i].simValue, p.SimValue()(r))
require.Equal(t, expected[i].subspace, p.Subspace())
}
}

View File

@ -0,0 +1,49 @@
package simulation
import (
"math/rand"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// Simulation operation weights constants
const (
DefaultWeightMsgUpdateParams int = 100
OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec
)
// ProposalMsgs defines the module weighted proposals' contents
func ProposalMsgs() []simtypes.WeightedProposalMsg {
return []simtypes.WeightedProposalMsg{
simulation.NewWeightedProposalMsg(
OpWeightMsgUpdateParams,
DefaultWeightMsgUpdateParams,
SimulateMsgUpdateParams,
),
}
}
// SimulateMsgUpdateParams returns a random MsgUpdateParams
func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg {
// use the default gov module account address as authority
var authority sdk.AccAddress = address.Module("gov")
params := types.DefaultParams()
params.BondDenom = simtypes.RandStringOfLength(r, 10)
params.HistoricalEntries = uint32(simtypes.RandIntBetween(r, 0, 1000))
params.MaxEntries = uint32(simtypes.RandIntBetween(r, 1, 1000))
params.MaxValidators = uint32(simtypes.RandIntBetween(r, 1, 1000))
params.UnbondingTime = time.Duration(simtypes.RandTimestamp(r).UnixNano())
params.MinCommissionRate = simtypes.RandomDecAmount(r, sdk.NewDec(1))
return &types.MsgUpdateParams{
Authority: authority.String(),
Params: params,
}
}

View File

@ -0,0 +1,47 @@
package simulation_test
import (
"math/rand"
"testing"
"time"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"gotest.tools/v3/assert"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
func TestProposalMsgs(t *testing.T) {
// initialize parameters
s := rand.NewSource(1)
r := rand.New(s)
ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
accounts := simtypes.RandomAccounts(r, 3)
// execute ProposalMsgs function
weightedProposalMsgs := simulation.ProposalMsgs()
assert.Assert(t, len(weightedProposalMsgs) == 1)
w0 := weightedProposalMsgs[0]
// tests w0 interface:
assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey())
assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight())
msg := w0.MsgSimulatorFn()(r, ctx, accounts)
msgUpdateParams, ok := msg.(*types.MsgUpdateParams)
assert.Assert(t, ok)
assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority)
assert.Equal(t, "GqiQWIXnku", msgUpdateParams.Params.BondDenom)
assert.Equal(t, uint32(213), msgUpdateParams.Params.MaxEntries)
assert.Equal(t, uint32(300), msgUpdateParams.Params.HistoricalEntries)
assert.Equal(t, uint32(539), msgUpdateParams.Params.MaxValidators)
assert.Equal(t, 8898194435*time.Second, msgUpdateParams.Params.UnbondingTime)
assert.DeepEqual(t, sdk.NewDecWithPrec(579040435581502128, 18), msgUpdateParams.Params.MinCommissionRate)
}

View File

@ -100,6 +100,10 @@ func (p Params) Validate() error {
return err
}
if err := validateHistoricalEntries(p.HistoricalEntries); err != nil {
return err
}
return nil
}