Skip to content

Commit

Permalink
Simulation docs (#5033)
Browse files Browse the repository at this point in the history
* simulation docs

* update docs with the latest simulation changes

* minor imporvments

* clean up of simulation.md

* expand section on weights

* minor reword

* minor wording fix

Co-authored-by: Marko <marbar3778@yahoo.com>
  • Loading branch information
fedekunze and tac0turtle authored Jan 31, 2020
1 parent 6890feb commit c7a6299
Show file tree
Hide file tree
Showing 6 changed files with 1,396 additions and 1,001 deletions.
123 changes: 123 additions & 0 deletions docs/building-modules/simulator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Module Simulation

## Prerequisites

* [Cosmos Blockchain Simulator](./../using-the-sdk/simulation.md)

## Synopsis

This document details how to define each module simulation functions to be
integrated with the application `SimulationManager`.

* [Simulation package](#simulation-package)
* [Store decoders](#store-decoders)
* [Randomized genesis](#randomized-genesis)
* [Randomized parameters](#randomized-parameters)
* [Random weighted operations](#random-weighted-operations)
* [Random proposal contents](#random-proposal-contents)
* [Registering the module simulation functions](#registering-simulation-functions)
* [App simulator manager](#app-simulator-manager)
* [Simulation tests](#simulation-tests)

## Simulation package

Every module that implements the SDK simulator needs to have a `x/<module>/simulation`
package which contains the primary functions required by the fuzz tests: store
decoders, randomized genesis state and parameters, weighted operations and proposal
contents.

### Store decoders

Registering the store decoders is required for the `AppImportExport`. This allows
for the key-value pairs from the stores to be decoded (_i.e_ unmarshalled)
to their corresponding types. In particular, it matches the key to a concrete type
and then unmarshals the value from the `KVPair` to the type provided.

You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders.

### Randomized genesis

The simulator tests different scenarios and values for genesis parameters
in order to fully test the edge cases of specific modules. The `simulator` package from each module must expose a `RandomizedGenState` function to generate the initial random `GenesisState` from a given seed. In

Once the module genesis parameter are generated randomly (or with the key and
values defined in a `params` file), they are marshaled to JSON format and added
to the app genesis JSON to use it on the simulations.

You can check an example on how to create the randomized genesis [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/staking/simulation/genesis.go).

### Randomized parameter changes

The simulator is able to test parameter changes at random. The simulator package from each module must contain a `RandomizedParams` func that will simulate parameter changes of the module throughout the simulations lifespan.

You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/staking/simulation/params.go)

### Random weighted operations

Operations are one of the crucial parts of the SDK simulation. They are the transactions
(`Msg`) that are simulated with random field values. The sender of the operation
is also assigned randomly.

Operations on the simulation are simulated using the full [transaction cycle](../core/transactions.md) of a
`ABCI` application that exposes the `BaseApp`.

Shown below is how weights are set:

+++ https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/staking/simulation/operations.go#L18-L92

As you can see the weights are predefined in this case but there are options on how to override this behavior with different weights. One is allowing `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights.

Here is how one can override the above package `simappparams`.

+++ https://github.com/cosmos/gaia/blob/master/sims.mk#L9-L22

For the last test a tool called runsim <!-- # TODO: add link to runsim readme when its created --> is used, this is used to parallelize go test instances, provide info to Github and slack integrations to provide information to your team on how the simulations are running.

### Random proposal contents

Randomized governance proposals are also supported on the SDK simulator. Each
module must define the governance proposal `Content`s that they expose and register
them to be used on the parameters.

## Registering simulation functions

Now that all the required functions are defined, we need to integrate them into the module pattern within the `module.go`:

+++ https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/distribution/module.go#L156-L185

## App Simulator manager

The following step is setting up the `SimulatorManager` at the app level. This
is required for the simulation test files on the next step.

```go
type CustomApp struct {
...
sm *module.SimulationManager
}
```

Then at the instantiation of the application, we create the `SimulationManager`
instance in the same way we create the `ModuleManager` but this time we only pass
the modules that implement the simulation functions from the `AppModuleSimulation`
interface described above.

```go
func NewCustomApp(...) {
// create the simulation manager and define the order of the modules for deterministic simulations
app.sm = module.NewSimulationManager(
auth.NewAppModule(app.accountKeeper),
bank.NewAppModule(app.bankKeeper, app.accountKeeper),
supply.NewAppModule(app.supplyKeeper, app.accountKeeper),
ov.NewAppModule(app.govKeeper, app.accountKeeper, app.supplyKeeper),
mint.NewAppModule(app.mintKeeper),
distr.NewAppModule(app.distrKeeper, app.accountKeeper, app.supplyKeeper, app.stakingKeeper),
staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper),
slashing.NewAppModule(app.slashingKeeper, app.accountKeeper, app.stakingKeeper),
)

// register the store decoders for simulation tests
app.sm.RegisterStoreDecoders()
...
}
```
17 changes: 12 additions & 5 deletions docs/building-modules/structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ x/{module}
│   ├── params.go
│   ├── ...
│   └── querier.go
├── simulation
│   ├── decoder.go
│   ├── genesis.go
│   ├── operations.go
│   ├── params.go
│   └── proposals.go
├── abci.go
├── alias.go
├── genesis.go
├── handler.go
├── module.go
├── ...
└── simulation.go
└── module.go
```

- `abci.go`: The module's `BeginBlocker` and `EndBlocker` implementations (if any).
Expand All @@ -53,7 +58,7 @@ there is nothing preventing developers from importing other packages from the mo
(excluding`internal/`) but it is recommended that `alias.go` have everything
exposed that other modules may need. The majority of the exported values here will
typically come from `internal/` (see below).
- `client/`: The module's CLI and REST client functionality implementation and
- `client/`: The module's CLI and REST client functionality implementation and
testing.
- `exported/`: The module's exported types -- typically type interfaces. If a module
relies on other module keepers, it is expected to receive them as interface
Expand All @@ -79,8 +84,10 @@ allows for greater freedom of development while maintaining API stability.
implementations such as the querier and invariants.
- `module.go`: The module's implementation of the `AppModule` and `AppModuleBasic`
interfaces.
- `simulation.go`: The module's simulation messages and related types (if any).
- `simulation/`: The module's simulation package defines all the required functions
used on the blockchain simulator: randomized genesis state, parameters, weigthed
operations, proposal contents and types decoders.

## Next {hide}

Learn about [interfaces](../interfaces/interfaces-intro.md) {hide}
Learn about [interfaces](../interfaces/interfaces-intro.md) {hide}
Loading

0 comments on commit c7a6299

Please sign in to comment.