github.com/cosmos/cosmos-sdk@v0.50.10/types/module/simulation.go (about)

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