From 94b4db929c1479dcff10b15124fae3a48331b111 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 27 Jan 2023 21:44:39 +0100 Subject: [PATCH] fix: add simulation tests for new param change (#14728) (cherry picked from commit d3c319418514601a86c68552e8d76d54daa52a03) # Conflicts: # CHANGELOG.md # types/module/simulation.go # x/auth/simulation/params.go # x/bank/simulation/params.go # x/distribution/simulation/params.go # x/gov/simulation/operations.go # x/gov/simulation/operations_test.go # x/gov/simulation/params.go # x/mint/simulation/params.go # x/slashing/simulation/params.go # x/staking/simulation/params.go --- CHANGELOG.md | 16 +++ UPGRADING.md | 4 + testutil/sims/simulation_helpers.go | 3 +- types/module/simulation.go | 50 ++++++- types/simulation/types.go | 13 +- x/auth/module.go | 6 +- x/auth/simulation/params_test.go | 37 ------ x/auth/simulation/proposals.go | 47 +++++++ x/auth/simulation/proposals_test.go | 45 +++++++ x/authz/module/module.go | 6 - x/authz/msgs.go | 2 +- x/authz/simulation/operations.go | 8 +- x/bank/module.go | 6 +- x/bank/simulation/operations.go | 10 +- x/bank/simulation/params_test.go | 35 ----- x/bank/simulation/proposals.go | 43 ++++++ x/bank/simulation/proposals_test.go | 44 +++++++ x/capability/module.go | 5 - x/distribution/module.go | 7 +- x/distribution/simulation/operations.go | 10 +- x/distribution/simulation/params_test.go | 35 ----- x/distribution/simulation/proposals.go | 44 +++++++ x/distribution/simulation/proposals_test.go | 42 ++++++ x/evidence/module.go | 6 - x/feegrant/module/module.go | 6 - x/gov/module.go | 10 +- x/gov/simulation/operations.go | 139 ++++++++++++++++---- x/gov/simulation/operations_test.go | 104 ++++++++++++--- x/gov/simulation/params_test.go | 37 ------ x/gov/simulation/proposals.go | 25 +++- x/gov/simulation/proposals_test.go | 38 ++++-- x/group/module/module.go | 6 - x/mint/module.go | 6 +- x/mint/simulation/params_test.go | 37 ------ x/mint/simulation/proposals.go | 48 +++++++ x/mint/simulation/proposals_test.go | 46 +++++++ x/nft/simulation/operations.go | 5 +- x/params/module.go | 6 - x/params/simulation/operations.go | 4 +- x/params/simulation/operations_test.go | 4 +- x/params/simulation/proposals.go | 4 +- x/params/simulation/proposals_test.go | 2 +- x/simulation/params.go | 62 ++++++--- x/simulation/params_test.go | 6 +- x/slashing/module.go | 6 +- x/slashing/simulation/operations.go | 6 +- x/slashing/simulation/params_test.go | 37 ------ x/slashing/simulation/proposals.go | 48 +++++++ x/slashing/simulation/proposals_test.go | 46 +++++++ x/staking/module.go | 6 +- x/staking/simulation/params_test.go | 37 ------ x/staking/simulation/proposals.go | 49 +++++++ x/staking/simulation/proposals_test.go | 47 +++++++ x/staking/types/params.go | 4 + 54 files changed, 979 insertions(+), 426 deletions(-) delete mode 100644 x/auth/simulation/params_test.go create mode 100644 x/auth/simulation/proposals.go create mode 100644 x/auth/simulation/proposals_test.go delete mode 100644 x/bank/simulation/params_test.go create mode 100644 x/bank/simulation/proposals.go create mode 100644 x/bank/simulation/proposals_test.go delete mode 100644 x/distribution/simulation/params_test.go create mode 100644 x/distribution/simulation/proposals.go create mode 100644 x/distribution/simulation/proposals_test.go delete mode 100644 x/gov/simulation/params_test.go delete mode 100644 x/mint/simulation/params_test.go create mode 100644 x/mint/simulation/proposals.go create mode 100644 x/mint/simulation/proposals_test.go delete mode 100644 x/slashing/simulation/params_test.go create mode 100644 x/slashing/simulation/proposals.go create mode 100644 x/slashing/simulation/proposals_test.go delete mode 100644 x/staking/simulation/params_test.go create mode 100644 x/staking/simulation/proposals.go create mode 100644 x/staking/simulation/proposals_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index a39296dff22..838bd4e2b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -222,6 +222,22 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +<<<<<<< HEAD +======= +* (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`. +* (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`. +* (tx) [#14634](https://github.com/cosmos/cosmos-sdk/pull/14634) Move the `tx` go module to `x/tx`. +* (snapshots) [#14597](https://github.com/cosmos/cosmos-sdk/pull/14597) Move `snapshots` to `store/snapshots`, rename and bump proto package to v1. +* (crypto/keyring) [#14151](https://github.com/cosmos/cosmos-sdk/pull/14151) Move keys presentation from `crypto/keyring` to `client/keys` +* (modules) [#13850](https://github.com/cosmos/cosmos-sdk/pull/13850) and [#14046](https://github.com/cosmos/cosmos-sdk/pull/14046) Remove gogoproto stringer annotations. This removes the custom `String()` methods on all types that were using the annotations. +* (x/auth) [#13850](https://github.com/cosmos/cosmos-sdk/pull/13850/) Remove `MarshalYAML` methods from module (`x/...`) types. +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) * (x/auth) [#13877](https://github.com/cosmos/cosmos-sdk/pull/13877) Rename `AccountKeeper`'s `GetNextAccountNumber` to `NextAccountNumber`. * (x/evidence) [#13740](https://github.com/cosmos/cosmos-sdk/pull/13740) The `NewQueryEvidenceRequest` function now takes `hash` as a HEX encoded `string`. * (server) [#13485](https://github.com/cosmos/cosmos-sdk/pull/13485) The `Application` service now requires the `RegisterNodeService` method to be implemented. diff --git a/UPGRADING.md b/UPGRADING.md index 505906d22d5..cc79611148e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -8,6 +8,10 @@ This guide provides instructions for upgrading to specific versions of Cosmos SD 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 diff --git a/testutil/sims/simulation_helpers.go b/testutil/sims/simulation_helpers.go index 4132007c090..2645162a146 100644 --- a/testutil/sims/simulation_helpers.go +++ b/testutil/sims/simulation_helpers.go @@ -63,7 +63,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) } diff --git a/types/module/simulation.go b/types/module/simulation.go index e7acb7e0cd8..a69d762ba8d 100644 --- a/types/module/simulation.go +++ b/types/module/simulation.go @@ -19,9 +19,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(sdk.StoreDecoderRegistry) @@ -29,6 +26,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 { @@ -78,12 +87,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 @@ -117,6 +142,7 @@ 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 { +<<<<<<< HEAD AppParams simulation.AppParams Cdc codec.JSONCodec // application codec Rand *rand.Rand // random number @@ -128,4 +154,20 @@ type SimulationState struct { 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 +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) } diff --git a/types/simulation/types.go b/types/simulation/types.go index 199f47fa38e..f218c814ba8 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -11,14 +11,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 @@ -28,9 +31,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 diff --git a/x/auth/module.go b/x/auth/module.go index 1c118c4ef2a..b980ff30f66 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -178,9 +178,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 diff --git a/x/auth/simulation/params_test.go b/x/auth/simulation/params_test.go deleted file mode 100644 index b8fb384a80f..00000000000 --- a/x/auth/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/auth/simulation/proposals.go b/x/auth/simulation/proposals.go new file mode 100644 index 00000000000..87746569c22 --- /dev/null +++ b/x/auth/simulation/proposals.go @@ -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, + } +} diff --git a/x/auth/simulation/proposals_test.go b/x/auth/simulation/proposals_test.go new file mode 100644 index 00000000000..285985cad31 --- /dev/null +++ b/x/auth/simulation/proposals_test.go @@ -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) +} diff --git a/x/authz/module/module.go b/x/authz/module/module.go index 16e4e7d84b2..a34f3c29aad 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -204,12 +204,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 sdk.StoreDecoderRegistry) { sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc) diff --git a/x/authz/msgs.go b/x/authz/msgs.go index d3c2afe28d8..fd84b311d7e 100644 --- a/x/authz/msgs.go +++ b/x/authz/msgs.go @@ -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 ( diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go index 39172a1e5ec..33fe08dea02 100644 --- a/x/authz/simulation/operations.go +++ b/x/authz/simulation/operations.go @@ -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 diff --git a/x/bank/module.go b/x/bank/module.go index 01b7df315c3..57bd9a4bd10 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -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(_ 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 diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 29d0b07df6e..a9a8be151e3 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -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 diff --git a/x/bank/simulation/params_test.go b/x/bank/simulation/params_test.go deleted file mode 100644 index df6604367a1..00000000000 --- a/x/bank/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/bank/simulation/proposals.go b/x/bank/simulation/proposals.go new file mode 100644 index 00000000000..5a63b8632ce --- /dev/null +++ b/x/bank/simulation/proposals.go @@ -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, + } +} diff --git a/x/bank/simulation/proposals_test.go b/x/bank/simulation/proposals_test.go new file mode 100644 index 00000000000..8fa38af0105 --- /dev/null +++ b/x/bank/simulation/proposals_test.go @@ -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) +} diff --git a/x/capability/module.go b/x/capability/module.go index 8971e9e8d4c..2d6ea9ef853 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -162,11 +162,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 sdk.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) diff --git a/x/distribution/module.go b/x/distribution/module.go index 432e3a851f9..a4060fb3d40 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -184,10 +184,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 diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index d4c8caa61eb..9a5e5de737b 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -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 diff --git a/x/distribution/simulation/params_test.go b/x/distribution/simulation/params_test.go deleted file mode 100644 index 0d1818a4051..00000000000 --- a/x/distribution/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/distribution/simulation/proposals.go b/x/distribution/simulation/proposals.go new file mode 100644 index 00000000000..6330691afc2 --- /dev/null +++ b/x/distribution/simulation/proposals.go @@ -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, + } +} diff --git a/x/distribution/simulation/proposals_test.go b/x/distribution/simulation/proposals_test.go new file mode 100644 index 00000000000..77d7d570716 --- /dev/null +++ b/x/distribution/simulation/proposals_test.go @@ -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) +} diff --git a/x/evidence/module.go b/x/evidence/module.go index 225c53c4d2f..220ef570a04 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -176,12 +176,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 sdk.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper) diff --git a/x/feegrant/module/module.go b/x/feegrant/module/module.go index f9c462fcafb..2db6ccb5b18 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -207,12 +207,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 sdk.StoreDecoderRegistry) { sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc) diff --git a/x/gov/module.go b/x/gov/module.go index b33ade55c2a..9f9ed4f6c71 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -331,10 +331,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 sdk.StoreDecoderRegistry) { sdr[govtypes.StoreKey] = simulation.NewDecodeStore(am.cdc) @@ -344,6 +349,7 @@ func (am AppModule) RegisterStoreDecoder(sdr sdk.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, ) } diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 09a56b44454..07523a968aa 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -25,6 +25,11 @@ var ( TypeMsgVote = sdk.MsgTypeURL(&v1.MsgVote{}) TypeMsgVoteWeighted = sdk.MsgTypeURL(&v1.MsgVoteWeighted{}) TypeMsgSubmitProposal = sdk.MsgTypeURL(&v1.MsgSubmitProposal{}) +<<<<<<< HEAD +======= + TypeMsgCancelProposal = sdk.MsgTypeURL(&v1.MsgCancelProposal{}) + TypeMsgUpdateParams = sdk.MsgTypeURL(&v1.MsgUpdateParams{}) +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) ) // Simulation operation weights constants @@ -42,7 +47,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 @@ -67,20 +72,46 @@ func WeightedOperations(appParams simtypes.AppParams, cdc codec.JSONCodec, ak ty }, ) +<<<<<<< HEAD // generate the weighted operations for the proposal contents +======= + appParams.GetOrGenerate(cdc, OpWeightMsgCancelProposal, &weightMsgCancelProposal, nil, + func(_ *rand.Rand) { + weightMsgCancelProposal = DefaultWeightMsgCancelProposal + }, + ) + + // generate the weighted operations for the proposal msgs +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) 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()), ), ) } @@ -100,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, @@ -153,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, msg.Type(), "unable to generate a submit proposal msg"), nil, err } diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 7192069311e..21c675d4b9f 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -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" @@ -34,20 +34,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)), @@ -55,13 +66,18 @@ func (m MockWeightedProposalContent) ContentSimulatorFn() simtypes.ContentSimula } } -// make sure the MockWeightedProposalContent satisfied the WeightedProposalContent interface -var _ simtypes.WeightedProposalContent = MockWeightedProposalContent{} +func mockWeightedProposalMsg(n int) []simtypes.WeightedProposalMsg { + wpc := make([]simtypes.WeightedProposalMsg, n) + for i := 0; i < n; i++ { + wpc[i] = MockWeightedProposals{i} + } + return wpc +} -func mockWeightedProposalContent(n int) []simtypes.WeightedProposalContent { - wpc := make([]simtypes.WeightedProposalContent, n) +func mockWeightedLegacyProposalContent(n int) []simtypes.WeightedProposalContent { //nolint:staticcheck + wpc := make([]simtypes.WeightedProposalContent, n) //nolint:staticcheck for i := 0; i < n; i++ { - wpc[i] = MockWeightedProposalContent{i} + wpc[i] = MockWeightedProposals{i} } return wpc } @@ -71,12 +87,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 @@ -89,17 +103,22 @@ 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}, +<<<<<<< HEAD +======= + {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}, +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) } 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 @@ -125,7 +144,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) @@ -280,12 +329,21 @@ func TestSimulateMsgVoteWeighted(t *testing.T) { } type suite struct { +<<<<<<< HEAD cdc codec.Codec AccountKeeper authkeeper.AccountKeeper BankKeeper bankkeeper.Keeper GovKeeper *keeper.Keeper StakingKeeper *stakingkeeper.Keeper App *runtime.App +======= + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + GovKeeper *keeper.Keeper + StakingKeeper *stakingkeeper.Keeper + DistributionKeeper dk.Keeper + App *runtime.App +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) } // returns context and an app with updated mint keeper @@ -300,7 +358,11 @@ func createTestSuite(t *testing.T, isCheckTx bool) (suite, sdk.Context) { configurator.StakingModule(), configurator.ConsensusModule(), configurator.GovModule(), +<<<<<<< HEAD ), &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, &res.cdc) +======= + ), &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, &res.DistributionKeeper) +>>>>>>> d3c319418 (fix: add simulation tests for new param change (#14728)) require.NoError(t, err) ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{}) diff --git a/x/gov/simulation/params_test.go b/x/gov/simulation/params_test.go deleted file mode 100644 index de528d14d9d..00000000000 --- a/x/gov/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/gov/simulation/proposals.go b/x/gov/simulation/proposals.go index 9a7bfdf2125..4afda5b0e49 100644 --- a/x/gov/simulation/proposals.go +++ b/x/gov/simulation/proposals.go @@ -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), diff --git a/x/gov/simulation/proposals_test.go b/x/gov/simulation/proposals_test.go index f3c4b61ff62..a90c7200812 100644 --- a/x/gov/simulation/proposals_test.go +++ b/x/gov/simulation/proposals_test.go @@ -4,14 +4,36 @@ import ( "math/rand" "testing" - "github.com/stretchr/testify/require" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "gotest.tools/v3/assert" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/gov/simulation" ) +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.OpWeightSubmitTextProposal, w0.AppParamsKey()) + assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) + + msg := w0.MsgSimulatorFn()(r, ctx, accounts) + assert.Assert(t, msg == nil) +} + func TestProposalContents(t *testing.T) { // initialize parameters s := rand.NewSource(1) @@ -22,18 +44,18 @@ func TestProposalContents(t *testing.T) { // execute ProposalContents function weightedProposalContent := simulation.ProposalContents() - require.Len(t, weightedProposalContent, 1) + assert.Assert(t, len(weightedProposalContent) == 1) w0 := weightedProposalContent[0] // tests w0 interface: - require.Equal(t, simulation.OpWeightMsgDeposit, w0.AppParamsKey()) - require.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) + assert.Equal(t, simulation.OpWeightMsgDeposit, w0.AppParamsKey()) + assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) content := w0.ContentSimulatorFn()(r, ctx, accounts) - require.Equal(t, "NxImpptHBIFDQfnxaTiOBJUgNzvqHbVcVJYlIFWFlzFqqRTTyFzDUMntPzyRamUFqeJAEaSHIuUHZoTWDjWXsYxYvwXwXZEsjRQKgKMselyUqWXMbHzRNDHnMzhWSirUgVggjiBxtWDfhzPDgrorEoNmDEiDdBldYegphCBTYWrmFFXNjxhtygsGBFHTejaKjMsqNdikEzDalEyWRHfJhKqifCKsedVuuJbQMbmRVuIPDluAWGpngjgBjOxuRFwSadayHNIhVVmNWBbfaTOldclxTTLUMvaBnLfwjHTtsKetEIvgrxLijhKJNablmvqpWIWsmhWQAYNLycREypoASHnyKWrxpoNLBJuyCGysZJgXbQAAmSIbGxMFXuwMVGZgBiZWfPWorAfjBeekCFvljHAtVZaTOsRxbPIioNxLTnWUTzGTvaNhplQQPmMADRRDuUIsiBpnGqPheKmLnopieVseFdTSAvOCacxaqFWFuXzsrVZzlGfeRpClwKuGEBujaPrzSLjVIOMvLlWxuznEOXlxbZroBRVEvEfBBAHOECribZNrYiFnzQqQmBnLksmFNAadusWAGltuqYNntgOlgOGwSdDjWdLboWyAWIcCfmpGJTfbljKPriLehwObuszICkaXNUkmeddeeRulbZBXJVLgteiKIfofGdNBregwUPlINQECatDSNXSIuefyMxxoKfcmjHEwbVtFiXtEnLJkLHUghmzFiymrgBChucZgOQUpGGVQEpRtIQjIBxYhtZPgUORdxXNWUMErWrUeriqYJPcgIDgLMWAyuuQnsHncCtjvHmvFbzYErxeunQllYDUVlXaRBveRUKeXwEGJFTSAqZtaBSDGDtzlADCnGjuTmYMJlapRsWfugmjwKEuoXJVpZvlcHeFvVvRRktRVGwzLfKezPEMABZtbLExQIjynSoahmkmoTHefdzFoBHMcQHFkKVHhpNtudPqJrYuQswzFuFHbSmpNltFnYJpvMrAYHFrNouZaanEUGHvbHIUUFTCtZrcpRHwgjblxlDNJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjf", content.GetDescription()) - require.Equal(t, "XhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeHVIkPZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", content.GetTitle()) - require.Equal(t, "gov", content.ProposalRoute()) - require.Equal(t, "Text", content.ProposalType()) + assert.Equal(t, "NxImpptHBIFDQfnxaTiOBJUgNzvqHbVcVJYlIFWFlzFqqRTTyFzDUMntPzyRamUFqeJAEaSHIuUHZoTWDjWXsYxYvwXwXZEsjRQKgKMselyUqWXMbHzRNDHnMzhWSirUgVggjiBxtWDfhzPDgrorEoNmDEiDdBldYegphCBTYWrmFFXNjxhtygsGBFHTejaKjMsqNdikEzDalEyWRHfJhKqifCKsedVuuJbQMbmRVuIPDluAWGpngjgBjOxuRFwSadayHNIhVVmNWBbfaTOldclxTTLUMvaBnLfwjHTtsKetEIvgrxLijhKJNablmvqpWIWsmhWQAYNLycREypoASHnyKWrxpoNLBJuyCGysZJgXbQAAmSIbGxMFXuwMVGZgBiZWfPWorAfjBeekCFvljHAtVZaTOsRxbPIioNxLTnWUTzGTvaNhplQQPmMADRRDuUIsiBpnGqPheKmLnopieVseFdTSAvOCacxaqFWFuXzsrVZzlGfeRpClwKuGEBujaPrzSLjVIOMvLlWxuznEOXlxbZroBRVEvEfBBAHOECribZNrYiFnzQqQmBnLksmFNAadusWAGltuqYNntgOlgOGwSdDjWdLboWyAWIcCfmpGJTfbljKPriLehwObuszICkaXNUkmeddeeRulbZBXJVLgteiKIfofGdNBregwUPlINQECatDSNXSIuefyMxxoKfcmjHEwbVtFiXtEnLJkLHUghmzFiymrgBChucZgOQUpGGVQEpRtIQjIBxYhtZPgUORdxXNWUMErWrUeriqYJPcgIDgLMWAyuuQnsHncCtjvHmvFbzYErxeunQllYDUVlXaRBveRUKeXwEGJFTSAqZtaBSDGDtzlADCnGjuTmYMJlapRsWfugmjwKEuoXJVpZvlcHeFvVvRRktRVGwzLfKezPEMABZtbLExQIjynSoahmkmoTHefdzFoBHMcQHFkKVHhpNtudPqJrYuQswzFuFHbSmpNltFnYJpvMrAYHFrNouZaanEUGHvbHIUUFTCtZrcpRHwgjblxlDNJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjf", content.GetDescription()) + assert.Equal(t, "XhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeHVIkPZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", content.GetTitle()) + assert.Equal(t, "gov", content.ProposalRoute()) + assert.Equal(t, "Text", content.ProposalType()) } diff --git a/x/group/module/module.go b/x/group/module/module.go index 4d42e0dbf1f..192ee56ab50 100644 --- a/x/group/module/module.go +++ b/x/group/module/module.go @@ -172,12 +172,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 sdk.StoreDecoderRegistry) { sdr[group.StoreKey] = simulation.NewDecodeStore(am.cdc) diff --git a/x/mint/module.go b/x/mint/module.go index d4776370853..eade90c626d 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -190,9 +190,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. diff --git a/x/mint/simulation/params_test.go b/x/mint/simulation/params_test.go deleted file mode 100644 index 3334fbd51a9..00000000000 --- a/x/mint/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/mint/simulation/proposals.go b/x/mint/simulation/proposals.go new file mode 100644 index 00000000000..129658adcf2 --- /dev/null +++ b/x/mint/simulation/proposals.go @@ -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, + } +} diff --git a/x/mint/simulation/proposals_test.go b/x/mint/simulation/proposals_test.go new file mode 100644 index 00000000000..eb14b31ad5b --- /dev/null +++ b/x/mint/simulation/proposals_test.go @@ -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) +} diff --git a/x/nft/simulation/operations.go b/x/nft/simulation/operations.go index 60e079cc08c..fca129d2164 100644 --- a/x/nft/simulation/operations.go +++ b/x/nft/simulation/operations.go @@ -16,13 +16,10 @@ import ( "github.com/cosmos/cosmos-sdk/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 ) diff --git a/x/params/module.go b/x/params/module.go index 90e7976ae65..827818edfcb 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -113,12 +113,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 sdk.StoreDecoderRegistry) {} diff --git a/x/params/simulation/operations.go b/x/params/simulation/operations.go index 6e7619b7032..fe6a5069e6b 100644 --- a/x/params/simulation/operations.go +++ b/x/params/simulation/operations.go @@ -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) diff --git a/x/params/simulation/operations_test.go b/x/params/simulation/operations_test.go index 5ed1ba8a50f..5e4f4e93e19 100644 --- a/x/params/simulation/operations_test.go +++ b/x/params/simulation/operations_test.go @@ -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) diff --git a/x/params/simulation/proposals.go b/x/params/simulation/proposals.go index 551f940754b..30b8f843479 100644 --- a/x/params/simulation/proposals.go +++ b/x/params/simulation/proposals.go @@ -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, diff --git a/x/params/simulation/proposals_test.go b/x/params/simulation/proposals_test.go index 1ae2b413259..e09202a6fe3 100644 --- a/x/params/simulation/proposals_test.go +++ b/x/params/simulation/proposals_test.go @@ -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) diff --git a/x/simulation/params.go b/x/simulation/params.go index acc7d9b6d8f..4ef3d2201a6 100644 --- a/x/simulation/params.go +++ b/x/simulation/params.go @@ -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 +} + +func NewWeightedProposalMsg(appParamsKey string, defaultWeight int, msgSimulatorFn simulation.MsgSimulatorFn) simulation.WeightedProposalMsg { + return &WeightedProposalMsg{appParamsKey: appParamsKey, defaultWeight: defaultWeight, msgSimulatorFn: msgSimulatorFn} +} + +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 } -// Proposal Contents +// Legacy Proposal Content -// WeightedProposalContent defines a common struct for proposal contents defined by -// external modules (i.e outside gov) +// 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 { diff --git a/x/simulation/params_test.go b/x/simulation/params_test.go index 90eb4f22a0a..23f0bb129f4 100644 --- a/x/simulation/params_test.go +++ b/x/simulation/params_test.go @@ -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 } diff --git a/x/slashing/module.go b/x/slashing/module.go index a18a2c8ea01..a1bb521603c 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -181,9 +181,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 diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index 939f28766fe..47c7155f035 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -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) { diff --git a/x/slashing/simulation/params_test.go b/x/slashing/simulation/params_test.go deleted file mode 100644 index 2f1933c60ad..00000000000 --- a/x/slashing/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/slashing/simulation/proposals.go b/x/slashing/simulation/proposals.go new file mode 100644 index 00000000000..6c17b9c44a0 --- /dev/null +++ b/x/slashing/simulation/proposals.go @@ -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, + } +} diff --git a/x/slashing/simulation/proposals_test.go b/x/slashing/simulation/proposals_test.go new file mode 100644 index 00000000000..4a8edf75e9c --- /dev/null +++ b/x/slashing/simulation/proposals_test.go @@ -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) +} diff --git a/x/staking/module.go b/x/staking/module.go index d693d47eb3f..c39724d6336 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -285,9 +285,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 diff --git a/x/staking/simulation/params_test.go b/x/staking/simulation/params_test.go deleted file mode 100644 index 07da026645c..00000000000 --- a/x/staking/simulation/params_test.go +++ /dev/null @@ -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()) - } -} diff --git a/x/staking/simulation/proposals.go b/x/staking/simulation/proposals.go new file mode 100644 index 00000000000..6b1f4312824 --- /dev/null +++ b/x/staking/simulation/proposals.go @@ -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, + } +} diff --git a/x/staking/simulation/proposals_test.go b/x/staking/simulation/proposals_test.go new file mode 100644 index 00000000000..4f3f79f67a5 --- /dev/null +++ b/x/staking/simulation/proposals_test.go @@ -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) +} diff --git a/x/staking/types/params.go b/x/staking/types/params.go index 448438e8a9a..f4e24e3f176 100644 --- a/x/staking/types/params.go +++ b/x/staking/types/params.go @@ -107,6 +107,10 @@ func (p Params) Validate() error { return err } + if err := validateHistoricalEntries(p.HistoricalEntries); err != nil { + return err + } + return nil }