Skip to content

Commit

Permalink
Remove dependency of types/module package on x/simulation (cosmos#5835)
Browse files Browse the repository at this point in the history
Closes: cosmos#5724
  • Loading branch information
jgimeno committed Mar 23, 2020
1 parent d657513 commit 49102b1
Show file tree
Hide file tree
Showing 51 changed files with 716 additions and 532 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ and `--pruning-snapshot-every` as an alternative to `--pruning`. They allow to f
be executed without an internet connection. Previously, `--generate-only` served this purpose in addition to only allowing
txs to be generated. Now, `--generate-only` solely allows txs to be generated without being broadcasted and disallows
Keybase use and `--offline` allows the use of Keybase but does not allow any functionality that requires an online connection.
* (types/module) [\#5724](https://github.com/cosmos/cosmos-sdk/issues/5724) The `types/module` package does no longer depend on `x/simulation`.

## [v0.38.1] - 2020-02-11

Expand Down
2 changes: 1 addition & 1 deletion simapp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package simapp
import (
"flag"

"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/types/simulation"
)

// List of available flags for the simulator
Expand Down
2 changes: 1 addition & 1 deletion simapp/helpers/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/tendermint/tendermint/crypto"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

// SimAppChainID hardcoded chainID for simulation
Expand Down
24 changes: 12 additions & 12 deletions simapp/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
simapparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

// AppStateFn returns the initial application state using a genesis or the simulation parameters.
// It panics if the user provides files for both of them.
// If a file is not given for the genesis or the sim params, it creates a randomized one.
func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simulation.AppStateFn {
return func(r *rand.Rand, accs []simulation.Account, config simulation.Config,
) (appState json.RawMessage, simAccs []simulation.Account, chainID string, genesisTimestamp time.Time) {
func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simtypes.AppStateFn {
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {

if FlagGenesisTimeValue == 0 {
genesisTimestamp = simulation.RandTimestamp(r)
genesisTimestamp = simtypes.RandTimestamp(r)
} else {
genesisTimestamp = time.Unix(FlagGenesisTimeValue, 0)
}
Expand All @@ -50,7 +50,7 @@ func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simulati
simAccs = accounts

case config.ParamsFile != "":
appParams := make(simulation.AppParams)
appParams := make(simtypes.AppParams)
bz, err := ioutil.ReadFile(config.ParamsFile)
if err != nil {
panic(err)
Expand All @@ -60,7 +60,7 @@ func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simulati
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)

default:
appParams := make(simulation.AppParams)
appParams := make(simtypes.AppParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
}

Expand All @@ -72,8 +72,8 @@ func AppStateFn(cdc *codec.Codec, simManager *module.SimulationManager) simulati
// and creates the simulation params
func AppStateRandomizedFn(
simManager *module.SimulationManager, r *rand.Rand, cdc *codec.Codec,
accs []simulation.Account, genesisTimestamp time.Time, appParams simulation.AppParams,
) (json.RawMessage, []simulation.Account) {
accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams,
) (json.RawMessage, []simtypes.Account) {
numAccs := int64(len(accs))
genesisState := NewDefaultGenesisState()

Expand Down Expand Up @@ -125,7 +125,7 @@ func AppStateRandomizedFn(

// AppStateFromGenesisFileFn util function to generate the genesis AppState
// from a genesis.json file.
func AppStateFromGenesisFileFn(r io.Reader, cdc *codec.Codec, genesisFile string) (tmtypes.GenesisDoc, []simulation.Account) {
func AppStateFromGenesisFileFn(r io.Reader, cdc *codec.Codec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) {
bytes, err := ioutil.ReadFile(genesisFile)
if err != nil {
panic(err)
Expand All @@ -142,7 +142,7 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc *codec.Codec, genesisFile string
cdc.MustUnmarshalJSON(appState[auth.ModuleName], &authGenesis)
}

newAccs := make([]simulation.Account, len(authGenesis.Accounts))
newAccs := make([]simtypes.Account, len(authGenesis.Accounts))
for i, acc := range authGenesis.Accounts {
// Pick a random private key, since we don't know the actual key
// This should be fine as it's only used for mock Tendermint validators
Expand All @@ -155,7 +155,7 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc *codec.Codec, genesisFile string
privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)

// create simulator accounts
simAcc := simulation.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.GetAddress()}
simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.GetAddress()}
newAccs[i] = simAcc
}

Expand Down
16 changes: 8 additions & 8 deletions simapp/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import (
"github.com/cosmos/cosmos-sdk/simapp/helpers"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/simulation"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
)

// SetupSimulation creates the config, db (levelDB), temporary directory and logger for
// the simulation tests. If `FlagEnabledValue` is false it skips the current test.
// Returns error on an invalid db intantiation or temp dir creation.
func SetupSimulation(dirPrefix, dbName string) (simulation.Config, dbm.DB, string, log.Logger, bool, error) {
func SetupSimulation(dirPrefix, dbName string) (simtypes.Config, dbm.DB, string, log.Logger, bool, error) {
if !FlagEnabledValue {
return simulation.Config{}, nil, "", nil, true, nil
return simtypes.Config{}, nil, "", nil, true, nil
}

config := NewConfigFromFlags()
Expand All @@ -36,22 +36,22 @@ func SetupSimulation(dirPrefix, dbName string) (simulation.Config, dbm.DB, strin

dir, err := ioutil.TempDir("", dirPrefix)
if err != nil {
return simulation.Config{}, nil, "", nil, false, err
return simtypes.Config{}, nil, "", nil, false, err
}

db, err := sdk.NewLevelDB(dbName, dir)
if err != nil {
return simulation.Config{}, nil, "", nil, false, err
return simtypes.Config{}, nil, "", nil, false, err
}

return config, db, dir, logger, false, nil
}

// SimulationOperations retrieves the simulation params from the provided file path
// and returns all the modules weighted operations
func SimulationOperations(app App, cdc *codec.Codec, config simulation.Config) []simulation.WeightedOperation {
func SimulationOperations(app App, cdc *codec.Codec, config simtypes.Config) []simtypes.WeightedOperation {
simState := module.SimulationState{
AppParams: make(simulation.AppParams),
AppParams: make(simtypes.AppParams),
Cdc: cdc,
}

Expand All @@ -72,7 +72,7 @@ func SimulationOperations(app App, cdc *codec.Codec, config simulation.Config) [
// CheckExportSimulation exports the app state and simulation parameters to JSON
// if the export paths are defined.
func CheckExportSimulation(
app App, config simulation.Config, params simulation.Params,
app App, config simtypes.Config, params simtypes.Params,
) error {
if config.ExportStatePath != "" {
fmt.Println("exporting app state...")
Expand Down
1 change: 0 additions & 1 deletion types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (

"github.com/gorilla/mux"
"github.com/spf13/cobra"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/cosmos/cosmos-sdk/client/context"
Expand Down
2 changes: 1 addition & 1 deletion types/module/simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/types/simulation"
)

// AppModuleSimulation defines the standard functions that every module should expose
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/types/simulation"
)

func TestRandomAccounts(t *testing.T) {
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/types/simulation"
)

func TestRandSubsetCoins(t *testing.T) {
Expand Down
12 changes: 12 additions & 0 deletions types/simulation/transition_matrix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package simulation

import "math/rand"

// TransitionMatrix is _almost_ a left stochastic matrix. It is technically
// not one due to not normalizing the column values. In the future, if we want
// to find the steady state distribution, it will be quite easy to normalize
// these values to get a stochastic matrix. Floats aren't currently used as
// the default due to non-determinism across architectures
type TransitionMatrix interface {
NextState(r *rand.Rand, i int) int
}
160 changes: 160 additions & 0 deletions types/simulation/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package simulation

import (
"encoding/json"
"math/rand"
"time"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)

type WeightedProposalContent interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
DefaultWeight() int // default weight
ContentSimulatorFn() ContentSimulatorFn // content simulator function
}

type ContentSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) Content

type Content interface {
GetTitle() string
GetDescription() string
ProposalRoute() string
ProposalType() string
ValidateBasic() error
String() string
}

type SimValFn func(r *rand.Rand) string

type ParamChange interface {
Subspace() string
Key() string
SimValue() SimValFn
ComposedKey() string
}

type WeightedOperation interface {
Weight() int
Op() Operation
}

// Operation runs a state machine transition, and ensures the transition
// happened as expected. The operation could be running and testing a fuzzed
// transaction, or doing the same for a message.
//
// For ease of debugging, an operation returns a descriptive message "action",
// which details what this fuzzed state machine transition actually did.
//
// Operations can optionally provide a list of "FutureOperations" to run later
// These will be ran at the beginning of the corresponding block.
type Operation func(r *rand.Rand, app *baseapp.BaseApp,
ctx sdk.Context, accounts []Account, chainID string) (
OperationMsg OperationMsg, futureOps []FutureOperation, err error)

// OperationMsg - structure for operation output
type OperationMsg struct {
Route string `json:"route" yaml:"route"` // msg route (i.e module name)
Name string `json:"name" yaml:"name"` // operation name (msg Type or "no-operation")
Comment string `json:"comment" yaml:"comment"` // additional comment
OK bool `json:"ok" yaml:"ok"` // success
Msg json.RawMessage `json:"msg" yaml:"msg"` // JSON encoded msg
}

// NewOperationMsgBasic creates a new operation message from raw input.
func NewOperationMsgBasic(route, name, comment string, ok bool, msg []byte) OperationMsg {
return OperationMsg{
Route: route,
Name: name,
Comment: comment,
OK: ok,
Msg: msg,
}
}

// NewOperationMsg - create a new operation message from sdk.Msg
func NewOperationMsg(msg sdk.Msg, ok bool, comment string) OperationMsg {
return NewOperationMsgBasic(msg.Route(), msg.Type(), comment, ok, msg.GetSignBytes())
}

// NoOpMsg - create a no-operation message
func NoOpMsg(route string) OperationMsg {
return NewOperationMsgBasic(route, "no-operation", "", false, nil)
}

// log entry text for this operation msg
func (om OperationMsg) String() string {
out, err := json.Marshal(om)
if err != nil {
panic(err)
}
return string(out)
}

// MustMarshal Marshals the operation msg, panic on error
func (om OperationMsg) MustMarshal() json.RawMessage {
out, err := json.Marshal(om)
if err != nil {
panic(err)
}
return out
}

// LogEvent adds an event for the events stats
func (om OperationMsg) LogEvent(eventLogger func(route, op, evResult string)) {
pass := "ok"
if !om.OK {
pass = "failure"
}
eventLogger(om.Route, om.Name, pass)
}

//________________________________________________________________________

// FutureOperation is an operation which will be ran at the beginning of the
// provided BlockHeight. If both a BlockHeight and BlockTime are specified, it
// will use the BlockHeight. In the (likely) event that multiple operations
// are queued at the same block height, they will execute in a FIFO pattern.
type FutureOperation struct {
BlockHeight int
BlockTime time.Time
Op Operation
}

// AppParams defines a flat JSON of key/values for all possible configurable
// simulation parameters. It might contain: operation weights, simulation parameters
// and flattened module state parameters (i.e not stored under it's respective module name).
type AppParams map[string]json.RawMessage

// GetOrGenerate attempts to get a given parameter by key from the AppParams
// object. If it exists, it'll be decoded and returned. Otherwise, the provided
// ParamSimulator is used to generate a random value or default value (eg: in the
// case of operation weights where Rand is not used).
func (sp AppParams) GetOrGenerate(cdc *codec.Codec, key string, ptr interface{}, r *rand.Rand, ps ParamSimulator) {
if v, ok := sp[key]; ok && v != nil {
cdc.MustUnmarshalJSON(v, ptr)
return
}

ps(r)
}

type ParamSimulator func(r *rand.Rand)

type SelectOpFn func(r *rand.Rand) Operation

// AppStateFn returns the app state json bytes and the genesis accounts
type AppStateFn func(r *rand.Rand, accs []Account, config Config) (
appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time,
)

type Params interface {
PastEvidenceFraction() float64
NumKeys() int
EvidenceFraction() float64
InitialLivenessWeightings() []int
LivenessTransitionMatrix() TransitionMatrix
BlockSizeTransitionMatrix() TransitionMatrix
}
Loading

0 comments on commit 49102b1

Please sign in to comment.