Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
* (x/gov) [#14782](https://github.com/cosmos/cosmos-sdk/pull/14782) Move the `metadata` argument in `govv1.NewProposal` alongside `title` and `summary`.

### Bug Fixes
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ require (
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6
google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1
gotest.tools/v3 v3.4.0
pgregory.net/rapid v0.5.3
sigs.k8s.io/yaml v1.3.0
)
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
3 changes: 2 additions & 1 deletion testutil/sims/simulation_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
58 changes: 43 additions & 15 deletions types/module/simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,25 @@ 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)

// simulation operations (i.e msgs) with their respective weight
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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -117,15 +142,18 @@ func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simu
// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
ParamChanges []simulation.ParamChange // simulated parameter changes from modules
Contents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
BondDenom string // denom to be used as default
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
//nolint:staticcheck
LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
ProposalMsgs []simulation.WeightedProposalMsg // proposal msg generator functions with their default weight and app sim key
}
13 changes: 12 additions & 1 deletion types/simulation/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions x/auth/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 0 additions & 40 deletions x/auth/simulation/params.go

This file was deleted.

37 changes: 0 additions & 37 deletions x/auth/simulation/params_test.go

This file was deleted.

47 changes: 47 additions & 0 deletions x/auth/simulation/proposals.go
Original file line number Diff line number Diff line change
@@ -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,
}
}
45 changes: 45 additions & 0 deletions x/auth/simulation/proposals_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
6 changes: 0 additions & 6 deletions x/authz/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion x/authz/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ 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"

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 (
Expand Down
Loading