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  }