Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.
/ cosmos-sdk Public archive
forked from cosmos/cosmos-sdk

Commit

Permalink
fix: add simulation tests for new param change (cosmos#14728)
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt authored and tsenart committed Apr 12, 2023
1 parent 8786b8d commit 0b2e6a8
Show file tree
Hide file tree
Showing 61 changed files with 933 additions and 712 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,11 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
* (x/upgrade) [14764](https://github.com/cosmos/cosmos-sdk/pull/14764) The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module.
* (x/gov) [#14782](https://github.com/cosmos/cosmos-sdk/pull/14782) Move the `metadata` argument in `govv1.NewProposal` alongside `title` and `summary`.
* (store) [#14746](https://github.com/cosmos/cosmos-sdk/pull/14746) Extract Store in its own go.mod and rename the package to `cosmossdk.io/store`.
* (x/simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
* (simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
* (crypto/keyring) [#13734](https://github.com/cosmos/cosmos-sdk/pull/13834) The keyring's `Sign` method now takes a new `signMode` argument. It is only used if the signing key is a Ledger hardware device. You can set it to 0 in all other cases.
* (x/evidence) [14724](https://github.com/cosmos/cosmos-sdk/pull/14724) Extract Evidence in its own go.mod and rename the package to `cosmossdk.io/x/evidence`.
* (x/nft) [#14725](https://github.com/cosmos/cosmos-sdk/pull/14725) Extract NFT in its own go.mod and rename the package to `cosmossdk.io/x/nft`.
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ All the upgrade imports are now renamed to use `cosmossdk.io/x/upgrade` instead

Remove `RandomizedParams` from `AppModuleSimulation` interface. Previously, it used to generate random parameter changes during simulations, however, it does so through ParamChangeProposal which is now legacy. Since all modules were migrated, we can now safely remove this from `AppModuleSimulation` interface.

Moreover, to support the `MsgUpdateParams` governance proposals for each modules, `AppModuleSimulation` now defines a `AppModule.ProposalMsgs` method in addition to `AppModule.ProposalContents`. That method defines the messages that can be used to submit a proposal and that should be tested in simulation.

When a module has no proposal messages or proposal content to be tested by simulation, the `AppModule.ProposalMsgs` and `AppModule.ProposalContents` methods can be deleted.

### gRPC

A new gRPC service, `proto/cosmos/base/node/v1beta1/query.proto`, has been introduced
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 @@ -68,7 +68,8 @@ func SimulationOperations(app runtime.AppI, cdc codec.JSONCodec, config simtypes
}
}

simState.Contents = app.SimulationManager().GetProposalContents(simState)
simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck
simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState)
return app.SimulationManager().WeightedOperations(simState)
}

Expand Down
59 changes: 43 additions & 16 deletions types/module/simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,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(simulation.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 @@ -76,12 +85,28 @@ func NewSimulationManagerFromAppModules(modules map[string]interface{}, override
return NewSimulationManager(simModules...)
}

// Deprecated: Use GetProposalMsgs instead.
// GetProposalContents returns each module's proposal content generator function
// with their default operation weight and key.
func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
for _, module := range sm.Modules {
wContents = append(wContents, module.ProposalContents(simState)...)
if module, ok := module.(HasProposalContents); ok {
wContents = append(wContents, module.ProposalContents(simState)...)
}
}

return wContents
}

// GetProposalMsgs returns each module's proposal msg generator function
// with their default operation weight and key.
func (sm *SimulationManager) GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg {
wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules))
for _, module := range sm.Modules {
if module, ok := module.(HasProposalMsgs); ok {
wContents = append(wContents, module.ProposalMsgs(simState)...)
}
}

return wContents
Expand Down Expand Up @@ -115,16 +140,18 @@ func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simu
// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
BondDenom string // denom to be used as default
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
ParamChanges []simulation.ParamChange // simulated parameter changes from modules
Contents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
AppParams simulation.AppParams
Cdc codec.JSONCodec // application codec
Rand *rand.Rand // random number
GenState map[string]json.RawMessage // genesis state
Accounts []simulation.Account // simulation accounts
InitialStake sdkmath.Int // initial coins per account
NumBonded int64 // number of initially bonded accounts
BondDenom string // denom to be used as default
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
//nolint:staticcheck
LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
ProposalMsgs []simulation.WeightedProposalMsg // proposal msg generator functions with their default weight and app sim key
}
13 changes: 12 additions & 1 deletion types/simulation/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
)

// Deprecated: Use WeightedProposalMsg instead.
type WeightedProposalContent interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
DefaultWeight() int // default weight
ContentSimulatorFn() ContentSimulatorFn // content simulator function
}

// Deprecated: Use MsgSimulatorFn instead.
type ContentSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) Content

// Deprecated: Use MsgSimulatorFn instead.
type Content interface {
GetTitle() string
GetDescription() string
Expand All @@ -29,9 +32,17 @@ type Content interface {
String() string
}

type WeightedProposalMsg interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
DefaultWeight() int // default weight
MsgSimulatorFn() MsgSimulatorFn // msg simulator function
}

type MsgSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) sdk.Msg

type SimValFn func(r *rand.Rand) string

type ParamChange interface {
type LegacyParamChange interface {
Subspace() string
Key() string
SimValue() SimValFn
Expand Down
6 changes: 3 additions & 3 deletions x/auth/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ func (am AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState, am.randGenAccountsFn)
}

// ProposalContents doesn't return any content functions for governance proposals.
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
// ProposalMsgs returns msgs used for governance proposals for simulations.
func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs()
}

// RegisterStoreDecoder registers a decoder for auth module's types
Expand Down
38 changes: 0 additions & 38 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 @@ -207,12 +207,6 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}

// ProposalContents returns all the authz content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}

// RegisterStoreDecoder registers a decoder for authz module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc)
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
8 changes: 3 additions & 5 deletions x/authz/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 0b2e6a8

Please sign in to comment.