2019-08-13 15:16:03 -07:00
|
|
|
package module
|
|
|
|
|
|
|
|
import (
|
2019-08-28 07:58:25 -07:00
|
|
|
"encoding/json"
|
2019-12-05 01:29:54 -08:00
|
|
|
|
2019-08-28 07:58:25 -07:00
|
|
|
"math/rand"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2019-08-13 15:16:03 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-03-23 04:55:44 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/simulation"
|
2019-08-13 15:16:03 -07:00
|
|
|
)
|
|
|
|
|
2019-08-28 07:58:25 -07:00
|
|
|
// AppModuleSimulation defines the standard functions that every module should expose
|
|
|
|
// for the SDK blockchain simulator
|
|
|
|
type AppModuleSimulation interface {
|
|
|
|
// randomized genesis states
|
|
|
|
GenerateGenesisState(input *SimulationState)
|
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
// content functions used to simulate governance proposals
|
|
|
|
ProposalContents(simState SimulationState) []simulation.WeightedProposalContent
|
|
|
|
|
2019-08-28 07:58:25 -07:00
|
|
|
// randomized module parameters for param change proposals
|
|
|
|
RandomizedParams(r *rand.Rand) []simulation.ParamChange
|
2019-12-05 01:29:54 -08:00
|
|
|
|
|
|
|
// 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
|
2019-08-28 07:58:25 -07:00
|
|
|
}
|
|
|
|
|
2019-08-13 15:16:03 -07:00
|
|
|
// 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 {
|
2019-08-28 07:58:25 -07:00
|
|
|
Modules []AppModuleSimulation // array of app modules; we use an array for deterministic simulation tests
|
|
|
|
StoreDecoders sdk.StoreDecoderRegistry // functions to decode the key-value pairs from each module's store
|
2019-08-13 15:16:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewSimulationManager creates a new SimulationManager object
|
2019-08-28 07:58:25 -07:00
|
|
|
//
|
|
|
|
// CONTRACT: All the modules provided must be also registered on the module Manager
|
|
|
|
func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager {
|
2019-08-13 15:16:03 -07:00
|
|
|
return &SimulationManager{
|
2019-08-28 07:58:25 -07:00
|
|
|
Modules: modules,
|
2019-08-13 15:16:03 -07:00
|
|
|
StoreDecoders: make(sdk.StoreDecoderRegistry),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
// GetProposalContents returns each module's proposal content generator function
|
|
|
|
// with their default operation weight and key.
|
|
|
|
func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
|
2020-02-05 11:32:45 -08:00
|
|
|
wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
|
2019-12-05 01:29:54 -08:00
|
|
|
for _, module := range sm.Modules {
|
|
|
|
wContents = append(wContents, module.ProposalContents(simState)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return wContents
|
|
|
|
}
|
|
|
|
|
2019-08-13 15:16:03 -07:00
|
|
|
// RegisterStoreDecoders registers each of the modules' store decoders into a map
|
|
|
|
func (sm *SimulationManager) RegisterStoreDecoders() {
|
|
|
|
for _, module := range sm.Modules {
|
|
|
|
module.RegisterStoreDecoder(sm.StoreDecoders)
|
|
|
|
}
|
|
|
|
}
|
2019-08-28 07:58:25 -07:00
|
|
|
|
|
|
|
// GenerateGenesisStates generates a randomized GenesisState for each of the
|
|
|
|
// registered modules
|
2019-12-05 01:29:54 -08:00
|
|
|
func (sm *SimulationManager) GenerateGenesisStates(simState *SimulationState) {
|
2019-08-28 07:58:25 -07:00
|
|
|
for _, module := range sm.Modules {
|
2019-12-05 01:29:54 -08:00
|
|
|
module.GenerateGenesisState(simState)
|
2019-08-28 07:58:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenerateParamChanges generates randomized contents for creating params change
|
|
|
|
// proposal transactions
|
|
|
|
func (sm *SimulationManager) GenerateParamChanges(seed int64) (paramChanges []simulation.ParamChange) {
|
|
|
|
r := rand.New(rand.NewSource(seed))
|
|
|
|
|
|
|
|
for _, module := range sm.Modules {
|
|
|
|
paramChanges = append(paramChanges, module.RandomizedParams(r)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-05 01:29:54 -08:00
|
|
|
// WeightedOperations returns all the modules' weighted operations of an application
|
|
|
|
func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simulation.WeightedOperation {
|
2020-02-05 11:32:45 -08:00
|
|
|
wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules))
|
2019-12-05 01:29:54 -08:00
|
|
|
for _, module := range sm.Modules {
|
|
|
|
wOps = append(wOps, module.WeightedOperations(simState)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return wOps
|
|
|
|
}
|
|
|
|
|
2019-08-28 07:58:25 -07:00
|
|
|
// SimulationState is the input parameters used on each of the module's randomized
|
|
|
|
// GenesisState generator function
|
|
|
|
type SimulationState struct {
|
|
|
|
AppParams simulation.AppParams
|
2019-12-05 01:29:54 -08:00
|
|
|
Cdc *codec.Codec // application codec
|
|
|
|
Rand *rand.Rand // random number
|
|
|
|
GenState map[string]json.RawMessage // genesis state
|
|
|
|
Accounts []simulation.Account // simulation accounts
|
|
|
|
InitialStake int64 // 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
|
2019-08-28 07:58:25 -07:00
|
|
|
}
|