github.com/Finschia/finschia-sdk@v0.48.1/types/module/simulation.go (about) 1 package module 2 3 import ( 4 "encoding/json" 5 "math/rand" 6 "sort" 7 "time" 8 9 "github.com/Finschia/finschia-sdk/codec" 10 sdk "github.com/Finschia/finschia-sdk/types" 11 "github.com/Finschia/finschia-sdk/types/simulation" 12 ) 13 14 // AppModuleSimulation defines the standard functions that every module should expose 15 // for the SDK blockchain simulator 16 type AppModuleSimulation interface { 17 // randomized genesis states 18 GenerateGenesisState(input *SimulationState) 19 20 // content functions used to simulate governance proposals 21 ProposalContents(simState SimulationState) []simulation.WeightedProposalContent 22 23 // randomized module parameters for param change proposals 24 RandomizedParams(r *rand.Rand) []simulation.ParamChange 25 26 // register a func to decode the each module's defined types from their corresponding store key 27 RegisterStoreDecoder(sdk.StoreDecoderRegistry) 28 29 // simulation operations (i.e msgs) with their respective weight 30 WeightedOperations(simState SimulationState) []simulation.WeightedOperation 31 } 32 33 // SimulationManager defines a simulation manager that provides the high level utility 34 // for managing and executing simulation functionalities for a group of modules 35 type SimulationManager struct { 36 Modules []AppModuleSimulation // array of app modules; we use an array for deterministic simulation tests 37 StoreDecoders sdk.StoreDecoderRegistry // functions to decode the key-value pairs from each module's store 38 } 39 40 // NewSimulationManager creates a new SimulationManager object 41 // 42 // CONTRACT: All the modules provided must be also registered on the module Manager 43 func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager { 44 return &SimulationManager{ 45 Modules: modules, 46 StoreDecoders: make(sdk.StoreDecoderRegistry), 47 } 48 } 49 50 // NewSimulationManagerFromAppModules creates a new SimulationManager object. 51 // 52 // First it sets any SimulationModule provided by overrideModules, and ignores any AppModule 53 // with the same moduleName. 54 // Then it attempts to cast every provided AppModule into an AppModuleSimulation. 55 // If the cast succeeds, its included, otherwise it is excluded. 56 func NewSimulationManagerFromAppModules(modules map[string]AppModule, overrideModules map[string]AppModuleSimulation) *SimulationManager { 57 simModules := []AppModuleSimulation{} 58 appModuleNamesSorted := make([]string, 0, len(modules)) 59 for moduleName := range modules { 60 appModuleNamesSorted = append(appModuleNamesSorted, moduleName) 61 } 62 63 sort.Strings(appModuleNamesSorted) 64 65 for _, moduleName := range appModuleNamesSorted { 66 // for every module, see if we override it. If so, use override. 67 // Else, if we can cast the app module into a simulation module add it. 68 // otherwise no simulation module. 69 if simModule, ok := overrideModules[moduleName]; ok { 70 simModules = append(simModules, simModule) 71 } else { 72 appModule := modules[moduleName] 73 if simModule, ok := appModule.(AppModuleSimulation); ok { 74 simModules = append(simModules, simModule) 75 } 76 // cannot cast, so we continue 77 } 78 } 79 return NewSimulationManager(simModules...) 80 } 81 82 // GetProposalContents returns each module's proposal content generator function 83 // with their default operation weight and key. 84 func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent { 85 wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules)) 86 for _, module := range sm.Modules { 87 wContents = append(wContents, module.ProposalContents(simState)...) 88 } 89 90 return wContents 91 } 92 93 // RegisterStoreDecoders registers each of the modules' store decoders into a map 94 func (sm *SimulationManager) RegisterStoreDecoders() { 95 for _, module := range sm.Modules { 96 module.RegisterStoreDecoder(sm.StoreDecoders) 97 } 98 } 99 100 // GenerateGenesisStates generates a randomized GenesisState for each of the 101 // registered modules 102 func (sm *SimulationManager) GenerateGenesisStates(simState *SimulationState) { 103 for _, module := range sm.Modules { 104 module.GenerateGenesisState(simState) 105 } 106 } 107 108 // GenerateParamChanges generates randomized contents for creating params change 109 // proposal transactions 110 func (sm *SimulationManager) GenerateParamChanges(seed int64) (paramChanges []simulation.ParamChange) { 111 r := rand.New(rand.NewSource(seed)) 112 113 for _, module := range sm.Modules { 114 paramChanges = append(paramChanges, module.RandomizedParams(r)...) 115 } 116 117 return 118 } 119 120 // WeightedOperations returns all the modules' weighted operations of an application 121 func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simulation.WeightedOperation { 122 wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules)) 123 for _, module := range sm.Modules { 124 wOps = append(wOps, module.WeightedOperations(simState)...) 125 } 126 127 return wOps 128 } 129 130 // SimulationState is the input parameters used on each of the module's randomized 131 // GenesisState generator function 132 type SimulationState struct { 133 AppParams simulation.AppParams 134 Cdc codec.JSONCodec // application codec 135 Rand *rand.Rand // random number 136 GenState map[string]json.RawMessage // genesis state 137 Accounts []simulation.Account // simulation accounts 138 InitialStake int64 // initial coins per account 139 NumBonded int64 // number of initially bonded accounts 140 GenTimestamp time.Time // genesis timestamp 141 UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration 142 ParamChanges []simulation.ParamChange // simulated parameter changes from modules 143 Contents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key 144 }