diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e8797df02b..aff26558340f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (simapp) [#14977](https://github.com/cosmos/cosmos-sdk/pull/14977) Move simulation helpers functions (`AppStateFn` and `AppStateRandomizedFn`) to `testutil/sims`. These takes an extra genesisState argument which is the default state of the app. * (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`. * (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. * (store) [#14189](https://github.com/cosmos/cosmos-sdk/pull/14189) Add config `iavl-lazy-loading` to enable lazy loading of iavl store, to improve start up time of archive nodes, add method `SetLazyLoading` to `CommitMultiStore` interface. diff --git a/simapp/params/params.go b/simapp/params/params.go deleted file mode 100644 index b6aa5fb55e0f..000000000000 --- a/simapp/params/params.go +++ /dev/null @@ -1,7 +0,0 @@ -package params - -// Simulation parameter constants -const ( - StakePerAccount = "stake_per_account" - InitiallyBondedValidators = "initially_bonded_validators" -) diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index 8a7b46a2b701..17ab7098e79a 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -49,7 +49,7 @@ func BenchmarkFullAppSimulation(b *testing.B) { b, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), @@ -104,7 +104,7 @@ func BenchmarkInvariants(b *testing.B) { b, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 5192c92eeea1..e3106b875cf1 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -92,7 +92,7 @@ func TestFullAppSimulation(t *testing.T) { t, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), @@ -137,7 +137,7 @@ func TestAppImportExport(t *testing.T) { t, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), @@ -253,7 +253,7 @@ func TestAppSimulationAfterImport(t *testing.T) { t, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), @@ -301,7 +301,7 @@ func TestAppSimulationAfterImport(t *testing.T) { t, os.Stdout, newApp.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), BlockedAddresses(), @@ -356,7 +356,7 @@ func TestAppStateDeterminism(t *testing.T) { t, os.Stdout, app.BaseApp, - AppStateFn(app.AppCodec(), app.SimulationManager()), + simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), BlockedAddresses(), diff --git a/simapp/state.go b/testutil/sims/state_helpers.go similarity index 82% rename from simapp/state.go rename to testutil/sims/state_helpers.go index ee1836ea7676..7b491b3b44ab 100644 --- a/simapp/state.go +++ b/testutil/sims/state_helpers.go @@ -1,4 +1,4 @@ -package simapp +package sims import ( "encoding/json" @@ -8,11 +8,10 @@ import ( "os" "time" + "cosmossdk.io/math" tmjson "github.com/tendermint/tendermint/libs/json" tmtypes "github.com/tendermint/tendermint/types" - "cosmossdk.io/math" - simappparams "cosmossdk.io/simapp/params" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" @@ -24,11 +23,21 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) +// Simulation parameter constants +const ( + StakePerAccount = "stake_per_account" + InitiallyBondedValidators = "initially_bonded_validators" +) + // 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.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { - return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, +// genesisState is the default genesis state of the whole app. +func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager, genesisState map[string]json.RawMessage) 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 simcli.FlagGenesisTimeValue == 0 { genesisTimestamp = simtypes.RandTimestamp(r) @@ -43,7 +52,10 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty case config.GenesisFile != "": // override the default chain-id from simapp to set it later to the config - genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) + genesisDoc, accounts, err := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) + if err != nil { + panic(err) + } if simcli.FlagGenesisTimeValue == 0 { // use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) @@ -65,11 +77,11 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty if err != nil { panic(err) } - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) default: appParams := make(simtypes.AppParams) - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) } rawState := make(map[string]json.RawMessage) @@ -84,8 +96,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty } stakingState := new(stakingtypes.GenesisState) - err = cdc.UnmarshalJSON(stakingStateBz, stakingState) - if err != nil { + if err = cdc.UnmarshalJSON(stakingStateBz, stakingState); err != nil { panic(err) } // compute not bonded balance @@ -104,8 +115,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty panic("bank genesis state is missing") } bankState := new(banktypes.GenesisState) - err = cdc.UnmarshalJSON(bankStateBz, bankState) - if err != nil { + if err = cdc.UnmarshalJSON(bankStateBz, bankState); err != nil { panic(err) } @@ -140,12 +150,15 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty // AppStateRandomizedFn creates calls each module's GenesisState generator function // and creates the simulation params func AppStateRandomizedFn( - simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, - accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, + simManager *module.SimulationManager, + r *rand.Rand, + cdc codec.JSONCodec, + accs []simtypes.Account, + genesisTimestamp time.Time, + appParams simtypes.AppParams, + genesisState map[string]json.RawMessage, ) (json.RawMessage, []simtypes.Account) { numAccs := int64(len(accs)) - genesisState := ModuleBasics.DefaultGenesis(cdc) - // generate a random amount of initial stake coins and a random initial // number of bonded accounts var ( @@ -153,11 +166,11 @@ func AppStateRandomizedFn( initialStake math.Int ) appParams.GetOrGenerate( - cdc, simappparams.StakePerAccount, &initialStake, r, + cdc, StakePerAccount, &initialStake, r, func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) }, ) appParams.GetOrGenerate( - cdc, simappparams.InitiallyBondedValidators, &numInitiallyBonded, r, + cdc, InitiallyBondedValidators, &numInitiallyBonded, r, func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, ) @@ -197,7 +210,7 @@ func AppStateRandomizedFn( // AppStateFromGenesisFileFn util function to generate the genesis AppState // from a genesis.json file. -func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) { +func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account, error) { bytes, err := os.ReadFile(genesisFile) if err != nil { panic(err) @@ -207,13 +220,12 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str // NOTE: Tendermint uses a custom JSON decoder for GenesisDoc err = tmjson.Unmarshal(bytes, &genesis) if err != nil { - panic(err) + return genesis, nil, err } - var appState GenesisState - err = json.Unmarshal(genesis.AppState, &appState) - if err != nil { - panic(err) + var appState map[string]json.RawMessage + if err = json.Unmarshal(genesis.AppState, &appState); err != nil { + return genesis, nil, err } var authGenesis authtypes.GenesisState @@ -235,7 +247,7 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str a, ok := acc.GetCachedValue().(authtypes.AccountI) if !ok { - panic("expected account") + return genesis, nil, fmt.Errorf("expected account") } // create simulator accounts @@ -243,5 +255,5 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str newAccs[i] = simAcc } - return genesis, newAccs + return genesis, newAccs, nil }