From c3299ef81cf46c17d03d404805f3c8454148607d Mon Sep 17 00:00:00 2001 From: Tanmay Date: Mon, 30 Sep 2024 15:00:16 +0530 Subject: [PATCH 01/22] debug sim test --- app/app.go | 9 +- app/encoding.go | 1 - app/modules.go | 119 ++++++++++++++++++ app/sim/sim_config.go | 75 +++++++++++ app/sim/sim_state.go | 283 ++++++++++++++++++++++++++++++++++++++++++ app/sim/sim_utils.go | 76 ++++++++++++ app/sim_test.go | 209 +++++++++++++++++++++++++++++++ sims.mk | 70 +++++++++++ 8 files changed, 840 insertions(+), 2 deletions(-) create mode 100644 app/modules.go create mode 100644 app/sim/sim_config.go create mode 100644 app/sim/sim_state.go create mode 100644 app/sim/sim_utils.go create mode 100644 app/sim_test.go create mode 100644 sims.mk diff --git a/app/app.go b/app/app.go index cc271fc35f..3f8c295b31 100644 --- a/app/app.go +++ b/app/app.go @@ -259,6 +259,7 @@ type App struct { mm *module.Manager sm *module.SimulationManager + ModuleBasics module.BasicManager configurator module.Configurator // sdk keepers @@ -737,6 +738,8 @@ func New( authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ) + app.ModuleBasics = newBasicManagerFromManager(app) + // During begin block slashing happens after distr.BeginBlocker so that // there is nothing left over in the validator fee pool, so as to keep the // CanWithdrawInvariant invariant. @@ -812,6 +815,10 @@ func New( app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) app.mm.RegisterServices(app.configurator) + app.sm = module.NewSimulationManager(simulationModules(app, appCodec, skipGenesisInvariants)...) + + app.sm.RegisterStoreDecoders() + // initialize stores app.MountKVStores(keys) app.MountTransientStores(tKeys) @@ -962,7 +969,7 @@ func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register legacy and grpc-gateway routes for all modules. - ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + app.ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // register app's OpenAPI routes. if apiConfig.Swagger { diff --git a/app/encoding.go b/app/encoding.go index 2e8c728b0f..dbf32a0878 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -14,7 +14,6 @@ import ( evmenc "github.com/zeta-chain/ethermint/encoding" ethermint "github.com/zeta-chain/ethermint/types" evmtypes "github.com/zeta-chain/ethermint/x/evm/types" - authoritytypes "github.com/zeta-chain/node/x/authority/types" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" emissionstypes "github.com/zeta-chain/node/x/emissions/types" diff --git a/app/modules.go b/app/modules.go new file mode 100644 index 0000000000..34e2660a6a --- /dev/null +++ b/app/modules.go @@ -0,0 +1,119 @@ +package app + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distr "github.com/cosmos/cosmos-sdk/x/distribution" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/evidence" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/gov" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/slashing" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// ModuleBasics defines the module BasicManager that is in charge of setting up basic, +// non-dependant module elements, such as codec registration +// and genesis verification. +func newBasicManagerFromManager(app *App) module.BasicManager { + var moduleBasics []module.AppModuleBasic + for _, m := range app.mm.Modules { + m, ok := m.(module.AppModuleBasic) + if !ok { + fmt.Printf("module %s is not an instance of module.AppModuleBasic\n", m) + continue + } + if m.Name() == govtypes.ModuleName { + m = gov.NewAppModuleBasic(getGovProposalHandlers()) + } + + if m.Name() == genutiltypes.ModuleName { + m = genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator) + } + + moduleBasics = append(moduleBasics, m) + } + basicManager := module.NewBasicManager(moduleBasics...) + //basicManager.RegisterLegacyAminoCodec(app.cdc) + basicManager.RegisterInterfaces(app.interfaceRegistry) + + return basicManager +} + +func simulationModules( + app *App, + appCodec codec.Codec, + _ bool, +) []module.AppModuleSimulation { + return []module.AppModuleSimulation{ + auth.NewAppModule(appCodec, app.AccountKeeper, RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), + gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), + slashing.NewAppModule( + appCodec, + app.SlashingKeeper, + app.AccountKeeper, + app.BankKeeper, + app.StakingKeeper, + app.GetSubspace(slashingtypes.ModuleName), + ), + params.NewAppModule(app.ParamsKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + } +} + +// RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. +// It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. +func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts { + genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts)) + for i, acc := range simState.Accounts { + bacc := authtypes.NewBaseAccountWithAddress(acc.Address) + + // Only consider making a vesting account once the initial bonded validator + // set is exhausted due to needing to track DelegatedVesting. + if !(int64(i) > simState.NumBonded && simState.Rand.Intn(100) < 50) { + genesisAccs[i] = bacc + continue + } + + initialVesting := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, simState.Rand.Int63n(simState.InitialStake.Int64()))) + var endTime int64 + + startTime := simState.GenTimestamp.Unix() + + // Allow for some vesting accounts to vest very quickly while others very slowly. + if simState.Rand.Intn(100) < 50 { + endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime)+1, int(startTime+(60*60*24*30)))) + } else { + endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime)+1, int(startTime+(60*60*12)))) + } + + bva := vestingtypes.NewBaseVestingAccount(bacc, initialVesting, endTime) + + if simState.Rand.Intn(100) < 50 { + genesisAccs[i] = vestingtypes.NewContinuousVestingAccountRaw(bva, startTime) + } else { + genesisAccs[i] = vestingtypes.NewDelayedVestingAccountRaw(bva) + } + } + + return genesisAccs +} diff --git a/app/sim/sim_config.go b/app/sim/sim_config.go new file mode 100644 index 0000000000..43c150303e --- /dev/null +++ b/app/sim/sim_config.go @@ -0,0 +1,75 @@ +package sim + +import ( + "flag" + + "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// List of available flags for the simulator +var ( + FlagGenesisFileValue string + FlagParamsFileValue string + FlagExportParamsPathValue string + FlagExportParamsHeightValue int + FlagExportStatePathValue string + FlagExportStatsPathValue string + FlagSeedValue int64 + FlagInitialBlockHeightValue int + FlagNumBlocksValue int + FlagBlockSizeValue int + FlagLeanValue bool + FlagCommitValue bool + FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation + FlagAllInvariantsValue bool + + FlagEnabledValue bool + FlagVerboseValue bool + FlagPeriodValue uint + FlagGenesisTimeValue int64 +) + +// GetSimulatorFlags gets the values of all the available simulation flags +func GetSimulatorFlags() { + // config fields + flag.StringVar(&FlagGenesisFileValue, "Genesis", "", "custom simulation genesis file; cannot be used with params file") + flag.StringVar(&FlagParamsFileValue, "Params", "", "custom simulation params file which overrides any random params; cannot be used with genesis") + flag.StringVar(&FlagExportParamsPathValue, "ExportParamsPath", "", "custom file path to save the exported params JSON") + flag.IntVar(&FlagExportParamsHeightValue, "ExportParamsHeight", 0, "height to which export the randomly generated params") + flag.StringVar(&FlagExportStatePathValue, "ExportStatePath", "", "custom file path to save the exported app state JSON") + flag.StringVar(&FlagExportStatsPathValue, "ExportStatsPath", "", "custom file path to save the exported simulation statistics JSON") + flag.Int64Var(&FlagSeedValue, "Seed", 42, "simulation random seed") + flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", 1, "initial block to start the simulation") + flag.IntVar(&FlagNumBlocksValue, "NumBlocks", 500, "number of new blocks to simulate from the initial block height") + flag.IntVar(&FlagBlockSizeValue, "BlockSize", 200, "operations per block") + flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output") + flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit") + flag.BoolVar(&FlagOnOperationValue, "SimulateEveryOperation", false, "run slow invariants every operation") + flag.BoolVar(&FlagAllInvariantsValue, "PrintAllInvariants", false, "print all invariants if a broken invariant is found") + + // simulation flags + flag.BoolVar(&FlagEnabledValue, "Enabled", false, "enable the simulation") + flag.BoolVar(&FlagVerboseValue, "Verbose", false, "verbose log output") + flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions") + flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", 0, "override genesis UNIX time instead of using a random UNIX time") +} + +// NewConfigFromFlags creates a simulation from the retrieved values of the flags. +func NewConfigFromFlags() simulation.Config { + return simulation.Config{ + GenesisFile: FlagGenesisFileValue, + ParamsFile: FlagParamsFileValue, + ExportParamsPath: FlagExportParamsPathValue, + ExportParamsHeight: FlagExportParamsHeightValue, + ExportStatePath: FlagExportStatePathValue, + ExportStatsPath: FlagExportStatsPathValue, + Seed: FlagSeedValue, + InitialBlockHeight: FlagInitialBlockHeightValue, + NumBlocks: FlagNumBlocksValue, + BlockSize: FlagBlockSizeValue, + Lean: FlagLeanValue, + Commit: FlagCommitValue, + OnOperation: FlagOnOperationValue, + AllInvariants: FlagAllInvariantsValue, + } +} diff --git a/app/sim/sim_state.go b/app/sim/sim_state.go new file mode 100644 index 0000000000..ad305d4720 --- /dev/null +++ b/app/sim/sim_state.go @@ -0,0 +1,283 @@ +package sim + +import ( + "encoding/json" + "fmt" + "io" + "math/rand" + "os" + "time" + + "cosmossdk.io/math" + cmtjson "github.com/cometbft/cometbft/libs/json" + tmtypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + zetaapp "github.com/zeta-chain/node/app" +) + +// 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.Codec, 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 FlagGenesisTimeValue == 0 { + genesisTimestamp = simtypes.RandTimestamp(r) + } else { + genesisTimestamp = time.Unix(FlagGenesisTimeValue, 0) + } + + chainID = config.ChainID + switch { + case config.ParamsFile != "" && config.GenesisFile != "": + panic("cannot provide both a genesis file and a params file") + + case config.GenesisFile != "": + // override the default chain-id from simapp to set it later to the config + genesisDoc, accounts, err := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) + if err != nil { + panic(err) + } + + if FlagGenesisTimeValue == 0 { + // use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) + genesisTimestamp = genesisDoc.GenesisTime + } + + appState = genesisDoc.AppState + chainID = genesisDoc.ChainID + simAccs = accounts + + case config.ParamsFile != "": + appParams := make(simtypes.AppParams) + bz, err := os.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &appParams) + if err != nil { + panic(err) + } + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) + + default: + appParams := make(simtypes.AppParams) + + genutilGenesis, ok := genesisState[genutiltypes.ModuleName] + if !ok { + panic("genutil genesis state is missing") + } + genutilState := new(genutiltypes.GenesisState) + err := cdc.UnmarshalJSON(genutilGenesis, genutilState) + if err != nil { + panic(err) + } + fmt.Println("Genesis transactions:", len(genutilState.GenTxs)) + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) + } + + rawState := make(map[string]json.RawMessage) + err := json.Unmarshal(appState, &rawState) + if err != nil { + panic(err) + } + + //genutilGenesis, ok := rawState[genutiltypes.ModuleName] + //if !ok { + // panic("genutil genesis state is missing") + //} + //genutilState := new(genutiltypes.GenesisState) + //err = cdc.UnmarshalJSON(genutilGenesis, genutilState) + //if err != nil { + // panic(err) + //} + // + //fmt.Println("Genesis transactions:", len(genutilState.GenTxs)) + // + //for _, acc := range genutilState.GenTxs { + // fmt.Println(acc) + //} + + stakingStateBz, ok := rawState[stakingtypes.ModuleName] + if !ok { + panic("staking genesis state is missing") + } + + stakingState := new(stakingtypes.GenesisState) + err = cdc.UnmarshalJSON(stakingStateBz, stakingState) + if err != nil { + panic(err) + } + // compute not bonded balance + notBondedTokens := math.ZeroInt() + for _, val := range stakingState.Validators { + if val.Status != stakingtypes.Unbonded { + continue + } + notBondedTokens = notBondedTokens.Add(val.GetTokens()) + } + notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) + // edit bank state to make it have the not bonded pool tokens + bankStateBz, ok := rawState[banktypes.ModuleName] + // TODO(fdymylja/jonathan): should we panic in this case + if !ok { + panic("bank genesis state is missing") + } + bankState := new(banktypes.GenesisState) + err = cdc.UnmarshalJSON(bankStateBz, bankState) + if err != nil { + panic(err) + } + + stakingAddr := authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String() + var found bool + for _, balance := range bankState.Balances { + if balance.Address == stakingAddr { + found = true + break + } + } + if !found { + bankState.Balances = append(bankState.Balances, banktypes.Balance{ + Address: stakingAddr, + Coins: sdk.NewCoins(notBondedCoins), + }) + } + + // change appState back + rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) + rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + + // replace appstate + appState, err = json.Marshal(rawState) + if err != nil { + panic(err) + } + return appState, simAccs, chainID, genesisTimestamp + } +} + +// AppStateRandomizedFn creates calls each module's GenesisState generator function +// and creates the simulation params +func AppStateRandomizedFn( + simManager *module.SimulationManager, r *rand.Rand, cdc codec.Codec, + accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, + genesisState map[string]json.RawMessage, +) (json.RawMessage, []simtypes.Account) { + numAccs := int64(len(accs)) + // generate a random amount of initial stake coins and a random initial + // number of bonded accounts + var ( + numInitiallyBonded int64 + initialStake math.Int + ) + + appParams.GetOrGenerate(cdc, + StakePerAccount, &initialStake, r, + func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) }, + ) + appParams.GetOrGenerate(cdc, + InitiallyBondedValidators, &numInitiallyBonded, r, + func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, + ) + + if numInitiallyBonded > numAccs { + numInitiallyBonded = numAccs + } + + fmt.Printf( + `Selected randomly generated parameters for simulated genesis: +{ + stake_per_account: "%d", + initially_bonded_validators: "%d" +} +`, initialStake, numInitiallyBonded, + ) + + simState := &module.SimulationState{ + AppParams: appParams, + Cdc: cdc, + Rand: r, + GenState: genesisState, + Accounts: accs, + InitialStake: initialStake, + NumBonded: numInitiallyBonded, + GenTimestamp: genesisTimestamp, + } + + simManager.GenerateGenesisStates(simState) + + appState, err := json.Marshal(genesisState) + if err != nil { + panic(err) + } + + return appState, accs +} + +// 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, error) { + bytes, err := os.ReadFile(genesisFile) + if err != nil { + panic(err) + } + + var genesis tmtypes.GenesisDoc + // NOTE: Comet uses a custom JSON decoder for GenesisDoc + err = cmtjson.Unmarshal(bytes, &genesis) + if err != nil { + panic(err) + } + + var appState zetaapp.GenesisState + err = json.Unmarshal(genesis.AppState, &appState) + if err != nil { + panic(err) + } + + var authGenesis authtypes.GenesisState + if appState[authtypes.ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[authtypes.ModuleName], &authGenesis) + } + + 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 + // and these keys are never actually used to sign by mock Tendermint. + privkeySeed := make([]byte, 15) + if _, err := r.Read(privkeySeed); err != nil { + panic(err) + } + + privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed) + + a, ok := acc.GetCachedValue().(authtypes.AccountI) + if !ok { + return genesis, nil, fmt.Errorf("expected account") + } + + // create simulator accounts + simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()} + newAccs[i] = simAcc + } + + return genesis, newAccs, nil +} diff --git a/app/sim/sim_utils.go b/app/sim/sim_utils.go new file mode 100644 index 0000000000..da915257f9 --- /dev/null +++ b/app/sim/sim_utils.go @@ -0,0 +1,76 @@ +package sim + +import ( + "encoding/json" + "fmt" + "os" + + dbm "github.com/cometbft/cometbft-db" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + zetaapp "github.com/zeta-chain/node/app" +) + +// SimulationOperations retrieves the simulation params from the provided file path +// and returns all the modules weighted operations +func SimulationOperations(app *zetaapp.App, cdc codec.JSONCodec, config simtypes.Config) []simtypes.WeightedOperation { + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + } + + if config.ParamsFile != "" { + bz, err := os.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &simState.AppParams) + if err != nil { + panic(err) + } + } + + simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck + simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState) + return app.SimulationManager().WeightedOperations(simState) +} + +// CheckExportSimulation exports the app state and simulation parameters to JSON +// if the export paths are defined. +func CheckExportSimulation(app runtime.AppI, config simtypes.Config, params simtypes.Params) error { + if config.ExportStatePath != "" { + fmt.Println("exporting app state...") + exported, err := app.ExportAppStateAndValidators(false, nil, nil) + if err != nil { + return err + } + + if err := os.WriteFile(config.ExportStatePath, []byte(exported.AppState), 0o600); err != nil { + return err + } + } + + if config.ExportParamsPath != "" { + fmt.Println("exporting simulation params...") + paramsBz, err := json.MarshalIndent(params, "", " ") + if err != nil { + return err + } + + if err := os.WriteFile(config.ExportParamsPath, paramsBz, 0o600); err != nil { + return err + } + } + return nil +} + +// PrintStats prints the corresponding statistics from the app DB. +func PrintStats(db dbm.DB) { + fmt.Println("\nLevelDB Stats") + fmt.Println(db.Stats()["leveldb.stats"]) + fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) +} diff --git a/app/sim_test.go b/app/sim_test.go new file mode 100644 index 0000000000..76fba034d8 --- /dev/null +++ b/app/sim_test.go @@ -0,0 +1,209 @@ +package app_test + +import ( + "encoding/json" + "fmt" + "math/rand" + "os" + "testing" + + "github.com/cometbft/cometbft/libs/log" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/ethermint/app" + evmante "github.com/zeta-chain/ethermint/app/ante" + evmtypes "github.com/zeta-chain/ethermint/x/evm/types" + zetaapp "github.com/zeta-chain/node/app" + "github.com/zeta-chain/node/app/ante" + + dbm "github.com/cometbft/cometbft-db" + + "github.com/cosmos/cosmos-sdk/store" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + simulation2 "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + + // "github.com/cosmos/gaia/v11/app/helpers" + // "github.com/cosmos/gaia/v11/app/params" + "github.com/zeta-chain/node/app/sim" +) + +// AppChainID hardcoded chainID for simulation + +func init() { + sim.GetSimulatorFlags() +} + +const ( + SimAppChainID = "simulation_777-1" + SimBlockMaxGas = 815000000 + TestAppChainID = "zetachain_777-1" +) + +// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail. +func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) (*zetaapp.App, error) { + + encCdc := zetaapp.MakeEncodingConfig() + app := zetaapp.New( + logger, + db, + nil, + false, + map[int64]bool{}, + app.DefaultNodeHome, + 5, + encCdc, + appOptions, + baseAppOptions..., + ) + // disable feemarket on native tx + options := ante.HandlerOptions{ + AccountKeeper: app.AccountKeeper, + BankKeeper: app.BankKeeper, + EvmKeeper: app.EvmKeeper, + FeeMarketKeeper: app.FeeMarketKeeper, + SignModeHandler: encCdc.TxConfig.SignModeHandler(), + SigGasConsumer: evmante.DefaultSigVerificationGasConsumer, + MaxTxGasWanted: 0, + ObserverKeeper: app.ObserverKeeper, + } + + anteHandler, err := ante.NewAnteHandler(options) + if err != nil { + panic(err) + } + + app.SetAnteHandler(anteHandler) + if err := app.LoadLatestVersion(); err != nil { + return nil, err + } + return app, nil +} + +// interBlockCacheOpt returns a BaseApp option function that sets the persistent +// inter-block write-through cache. +func interBlockCacheOpt() func(*baseapp.BaseApp) { + return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) +} + +// TODO: Make another test for the fuzzer itself, which just has noOp txs +// and doesn't depend on the application. +func TestAppStateDeterminism(t *testing.T) { + if !sim.FlagEnabledValue { + t.Skip("skipping application simulation") + } + + config := sim.NewConfigFromFlags() + config.InitialBlockHeight = 1 + config.ExportParamsPath = "" + config.OnOperation = false + config.AllInvariants = false + config.ChainID = SimAppChainID + + numSeeds := 3 + numTimesToRunPerSeed := 5 + + // We will be overriding the random seed and just run a single simulation on the provided seed value + if config.Seed != simcli.DefaultSeedValue { + numSeeds = 1 + } + + appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[server.FlagInvCheckPeriod] = sim.FlagPeriodValue + + for i := 0; i < numSeeds; i++ { + if config.Seed == simcli.DefaultSeedValue { + config.Seed = rand.Int63() + } + + fmt.Println("config.Seed: ", config.Seed) + + for j := 0; j < numTimesToRunPerSeed; j++ { + var logger log.Logger + if sim.FlagVerboseValue { + logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + } else { + logger = log.NewNopLogger() + } + + db := dbm.NewMemDB() + dir, err := os.MkdirTemp("", "zeta-simulation") + require.NoError(t, err) + appOptions[flags.FlagHome] = dir + + app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + + fmt.Printf( + "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + + blockedAddresses := app.ModuleAccountAddrs() + + _, _, err = simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + sim.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + blockedAddresses, + config, + app.AppCodec(), + ) + require.NoError(t, err) + + if config.Commit { + sim.PrintStats(db) + } + + appHash := app.LastCommitID().Hash + appHashList[j] = appHash + + if j != 0 { + require.Equal( + t, string(appHashList[0]), string(appHashList[j]), + "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + } + } + } +} + +func CFn(app *zetaapp.App) simulation2.AppStateFn { + var bondDenom string + return simtestutil.AppStateFnWithExtendedCbs( + app.AppCodec(), + app.SimulationManager(), + app.ModuleBasics.DefaultGenesis(app.AppCodec()), + func(moduleName string, genesisState interface{}) { + if moduleName == stakingtypes.ModuleName { + stakingState := genesisState.(*stakingtypes.GenesisState) + bondDenom = stakingState.Params.BondDenom + } + }, + func(rawState map[string]json.RawMessage) { + + evmStateBz, ok := rawState[evmtypes.ModuleName] + if !ok { + panic("evm genesis state is missing") + } + + evmState := new(evmtypes.GenesisState) + app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState) + + // we should replace the EvmDenom with BondDenom + evmState.Params.EvmDenom = bondDenom + + // change appState back + rawState[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmState) + }, + ) +} diff --git a/sims.mk b/sims.mk new file mode 100644 index 0000000000..c17cd9560a --- /dev/null +++ b/sims.mk @@ -0,0 +1,70 @@ +#!/usr/bin/make -f + +######################################## +### Simulations + +BINDIR ?= $(GOPATH)/bin +SIMAPP = ./app +test-sim-nondeterminism: + @echo "Running non-determinism test..." + @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ + -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + +test-sim-custom-genesis-fast: + @echo "Running custom genesis simulation..." + @echo "By default, ${HOME}/.gaia/config/genesis.json will be used." + @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.gaia/config/genesis.json \ + -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h + +test-sim-import-export: runsim + @echo "Running application import/export simulation. This may take several minutes..." + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport + +test-sim-after-import: runsim + @echo "Running application simulation-after-import. This may take several minutes..." + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport + +test-sim-custom-genesis-multi-seed: runsim + @echo "Running multi-seed custom genesis simulation..." + @echo "By default, ${HOME}/.gaia/config/genesis.json will be used." + @$(BINDIR)/runsim -Genesis=${HOME}/.gaia/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation + +test-sim-multi-seed-long: runsim + @echo "Running long multi-seed application simulation. This may take awhile!" + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation + +test-sim-multi-seed-short: runsim + @echo "Running short multi-seed application simulation. This may take awhile!" + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation + +test-sim-benchmark-invariants: + @echo "Running simulation invariant benchmarks..." + @go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \ + -Enabled=true -NumBlocks=1000 -BlockSize=200 \ + -Period=1 -Commit=true -Seed=57 -v -timeout 24h + +.PHONY: \ +test-sim-nondeterminism \ +test-sim-custom-genesis-fast \ +test-sim-import-export \ +test-sim-after-import \ +test-sim-custom-genesis-multi-seed \ +test-sim-multi-seed-short \ +test-sim-multi-seed-long \ +test-sim-benchmark-invariants + +SIM_NUM_BLOCKS ?= 500 +SIM_BLOCK_SIZE ?= 200 +SIM_COMMIT ?= true + +test-sim-benchmark: + @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" + @go test -mod=readonly -benchmem -run=^$$ $(SIMAPP) -bench ^BenchmarkFullAppSimulation$$ \ + -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h + +test-sim-profile: + @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" + @go test -mod=readonly -benchmem -run=^$$ $(SIMAPP) -bench ^BenchmarkFullAppSimulation$$ \ + -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out + +.PHONY: test-sim-profile test-sim-benchmark \ No newline at end of file From 7d9502118c40a1c2408438dcb98ac9aa5456cc96 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 12:51:14 +0530 Subject: [PATCH 02/22] start modifuing for v50 --- app/sim/sim_state.go | 61 ++++++++++++++++++++++++-------------------- go.mod | 2 +- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/app/sim/sim_state.go b/app/sim/sim_state.go index ad305d4720..8d03fd8fbe 100644 --- a/app/sim/sim_state.go +++ b/app/sim/sim_state.go @@ -78,17 +78,6 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt default: appParams := make(simtypes.AppParams) - - genutilGenesis, ok := genesisState[genutiltypes.ModuleName] - if !ok { - panic("genutil genesis state is missing") - } - genutilState := new(genutiltypes.GenesisState) - err := cdc.UnmarshalJSON(genutilGenesis, genutilState) - if err != nil { - panic(err) - } - fmt.Println("Genesis transactions:", len(genutilState.GenTxs)) appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) } @@ -98,22 +87,6 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt panic(err) } - //genutilGenesis, ok := rawState[genutiltypes.ModuleName] - //if !ok { - // panic("genutil genesis state is missing") - //} - //genutilState := new(genutiltypes.GenesisState) - //err = cdc.UnmarshalJSON(genutilGenesis, genutilState) - //if err != nil { - // panic(err) - //} - // - //fmt.Println("Genesis transactions:", len(genutilState.GenTxs)) - // - //for _, acc := range genutilState.GenTxs { - // fmt.Println(acc) - //} - stakingStateBz, ok := rawState[stakingtypes.ModuleName] if !ok { panic("staking genesis state is missing") @@ -160,6 +133,38 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt }) } + genustilStateBz, ok := rawState[genutiltypes.ModuleName] + if !ok { + panic("staking genesis state is missing") + } + + genutilState := new(genutiltypes.GenesisState) + err = cdc.UnmarshalJSON(genustilStateBz, genutilState) + if err != nil { + panic(err) + } + fmt.Println("------------------------------------------------") + fmt.Println("Genesis trasnactions :", len(genutilState.GenTxs)) + fmt.Println("Validators :", len(stakingState.Validators)) + max := 3 + for i, val := range stakingState.Validators { + if i == max { + break + } + fmt.Println("Validator :", val.OperatorAddress, val.Tokens, val.GetStatus()) + } + fmt.Println("Exported", stakingState.Exported) + fmt.Println("Bond Denom :", stakingState.Params.BondDenom) + fmt.Println("maxValidators", stakingState.Params.MaxValidators) + max = 3 + for i, val := range stakingState.LastValidatorPowers { + if i == max { + break + } + fmt.Println("LastValidatorPowers :", val.Address, val.Power) + } + fmt.Println("------------------------------------------------") + // change appState back rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) @@ -221,6 +226,8 @@ func AppStateRandomizedFn( GenTimestamp: genesisTimestamp, } + fmt.Println("Generating genesis states...") + simManager.GenerateGenesisStates(simState) appState, err := json.Marshal(genesisState) diff --git a/go.mod b/go.mod index 7625fc2047..17c8c18259 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft-db v0.12.0 github.com/cosmos/btcutil v1.0.5 - github.com/cosmos/cosmos-sdk v0.47.10 + github.com/cosmos/cosmos-sdk v0.50.9 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.4.0 github.com/davecgh/go-spew v1.1.1 From fcce58ee0d8443ce54b2ee88c927bc18858cc37c Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 19:15:55 +0530 Subject: [PATCH 03/22] add sim test v1 --- app/modules.go | 7 ++++++- app/sim/sim_state.go | 39 ++++++++++----------------------------- app/sim_test.go | 2 ++ go.mod | 2 +- sims.mk | 13 ++++++++++--- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/app/modules.go b/app/modules.go index 34e2660a6a..37151b717c 100644 --- a/app/modules.go +++ b/app/modules.go @@ -20,11 +20,14 @@ import ( genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" "github.com/cosmos/cosmos-sdk/x/params" "github.com/cosmos/cosmos-sdk/x/slashing" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/zeta-chain/ethermint/x/evm" + evmtypes "github.com/zeta-chain/ethermint/x/evm/types" ) // ModuleBasics defines the module BasicManager that is in charge of setting up basic, @@ -63,7 +66,7 @@ func simulationModules( return []module.AppModuleSimulation{ auth.NewAppModule(appCodec, app.AccountKeeper, RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), + //gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), slashing.NewAppModule( @@ -76,7 +79,9 @@ func simulationModules( ), params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), + evm.NewAppModule(app.EvmKeeper, app.AccountKeeper, app.GetSubspace(evmtypes.ModuleName)), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), } } diff --git a/app/sim/sim_state.go b/app/sim/sim_state.go index 8d03fd8fbe..12df57dc5c 100644 --- a/app/sim/sim_state.go +++ b/app/sim/sim_state.go @@ -18,8 +18,8 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + evmtypes "github.com/zeta-chain/ethermint/x/evm/types" zetaapp "github.com/zeta-chain/node/app" ) @@ -97,6 +97,7 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt if err != nil { panic(err) } + // compute not bonded balance notBondedTokens := math.ZeroInt() for _, val := range stakingState.Validators { @@ -133,39 +134,19 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt }) } - genustilStateBz, ok := rawState[genutiltypes.ModuleName] + evmStateBz, ok := rawState[evmtypes.ModuleName] if !ok { - panic("staking genesis state is missing") + panic("evm genesis state is missing") } - genutilState := new(genutiltypes.GenesisState) - err = cdc.UnmarshalJSON(genustilStateBz, genutilState) - if err != nil { - panic(err) - } - fmt.Println("------------------------------------------------") - fmt.Println("Genesis trasnactions :", len(genutilState.GenTxs)) - fmt.Println("Validators :", len(stakingState.Validators)) - max := 3 - for i, val := range stakingState.Validators { - if i == max { - break - } - fmt.Println("Validator :", val.OperatorAddress, val.Tokens, val.GetStatus()) - } - fmt.Println("Exported", stakingState.Exported) - fmt.Println("Bond Denom :", stakingState.Params.BondDenom) - fmt.Println("maxValidators", stakingState.Params.MaxValidators) - max = 3 - for i, val := range stakingState.LastValidatorPowers { - if i == max { - break - } - fmt.Println("LastValidatorPowers :", val.Address, val.Power) - } - fmt.Println("------------------------------------------------") + evmState := new(evmtypes.GenesisState) + cdc.MustUnmarshalJSON(evmStateBz, evmState) + + // we should replace the EvmDenom with BondDenom + evmState.Params.EvmDenom = stakingState.Params.BondDenom // change appState back + rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState) rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) diff --git a/app/sim_test.go b/app/sim_test.go index 76fba034d8..78fc003ccb 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -9,6 +9,7 @@ import ( "github.com/cometbft/cometbft/libs/log" servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/stretchr/testify/require" "github.com/zeta-chain/ethermint/app" @@ -62,6 +63,7 @@ func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, appOptions, baseAppOptions..., ) + sdk.DefaultPowerReduction = sdk.OneInt() // disable feemarket on native tx options := ante.HandlerOptions{ AccountKeeper: app.AccountKeeper, diff --git a/go.mod b/go.mod index 17c8c18259..7625fc2047 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft-db v0.12.0 github.com/cosmos/btcutil v1.0.5 - github.com/cosmos/cosmos-sdk v0.50.9 + github.com/cosmos/cosmos-sdk v0.47.10 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.4.0 github.com/davecgh/go-spew v1.1.1 diff --git a/sims.mk b/sims.mk index c17cd9560a..e48b22cf81 100644 --- a/sims.mk +++ b/sims.mk @@ -5,14 +5,21 @@ BINDIR ?= $(GOPATH)/bin SIMAPP = ./app + +runsim: $(BINDIR)/runsim +$(BINDIR)/runsim: + @echo "Installing runsim..." + @(cd /tmp && go install github.com/cosmos/tools/cmd/runsim@v1.0.0) + + test-sim-nondeterminism: @echo "Running non-determinism test..." @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ - -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h test-sim-custom-genesis-fast: @echo "Running custom genesis simulation..." - @echo "By default, ${HOME}/.gaia/config/genesis.json will be used." + @echo "By default, ${HOME}/.zetacored/config/genesis.json will be used." @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.gaia/config/genesis.json \ -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h @@ -26,7 +33,7 @@ test-sim-after-import: runsim test-sim-custom-genesis-multi-seed: runsim @echo "Running multi-seed custom genesis simulation..." - @echo "By default, ${HOME}/.gaia/config/genesis.json will be used." + @echo "By default, ${HOME}/.zetacored/config/genesis.json will be used." @$(BINDIR)/runsim -Genesis=${HOME}/.gaia/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation test-sim-multi-seed-long: runsim From b774b1e4f56ebea79c741a0b0a6b79265da10780 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 20:04:16 +0530 Subject: [PATCH 04/22] add sim export --- app/sim_test.go | 67 +++++++++++++++++++++++++++++-------------------- sims.mk | 51 ++++++------------------------------- 2 files changed, 47 insertions(+), 71 deletions(-) diff --git a/app/sim_test.go b/app/sim_test.go index 78fc003ccb..c13538f451 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -10,11 +10,9 @@ import ( "github.com/cometbft/cometbft/libs/log" servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/stretchr/testify/require" "github.com/zeta-chain/ethermint/app" evmante "github.com/zeta-chain/ethermint/app/ante" - evmtypes "github.com/zeta-chain/ethermint/x/evm/types" zetaapp "github.com/zeta-chain/node/app" "github.com/zeta-chain/node/app/ante" @@ -179,33 +177,48 @@ func TestAppStateDeterminism(t *testing.T) { } } -func CFn(app *zetaapp.App) simulation2.AppStateFn { - var bondDenom string - return simtestutil.AppStateFnWithExtendedCbs( - app.AppCodec(), - app.SimulationManager(), - app.ModuleBasics.DefaultGenesis(app.AppCodec()), - func(moduleName string, genesisState interface{}) { - if moduleName == stakingtypes.ModuleName { - stakingState := genesisState.(*stakingtypes.GenesisState) - bondDenom = stakingState.Params.BondDenom - } - }, - func(rawState map[string]json.RawMessage) { - - evmStateBz, ok := rawState[evmtypes.ModuleName] - if !ok { - panic("evm genesis state is missing") - } +func TestFullAppSimulation(t *testing.T) { + config := sim.NewConfigFromFlags() + config.ChainID = SimAppChainID + config.BlockMaxGas = SimBlockMaxGas + config.DBBackend = "memdb" + //config.ExportStatePath = "/Users/tanmay/.zetacored/simulation_state_export.json" - evmState := new(evmtypes.GenesisState) - app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState) + db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "mem-db", "Simulation", sim.FlagVerboseValue, sim.FlagEnabledValue) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") - // we should replace the EvmDenom with BondDenom - evmState.Params.EvmDenom = bondDenom + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[server.FlagInvCheckPeriod] = sim.FlagPeriodValue - // change appState back - rawState[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmState) - }, + app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + require.NoError(t, err) + + blockedAddresses := app.ModuleAccountAddrs() + _, _, simerr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + sim.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + blockedAddresses, + config, + app.AppCodec(), ) + require.NoError(t, simerr) + + // check export works as expected + _, err = app.ExportAppStateAndValidators(false, nil, nil) + require.NoError(t, err) + + if config.Commit { + simtestutil.PrintStats(db) + } } diff --git a/sims.mk b/sims.mk index e48b22cf81..fb8a11d6de 100644 --- a/sims.mk +++ b/sims.mk @@ -17,25 +17,11 @@ test-sim-nondeterminism: @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h -test-sim-custom-genesis-fast: - @echo "Running custom genesis simulation..." - @echo "By default, ${HOME}/.zetacored/config/genesis.json will be used." - @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.gaia/config/genesis.json \ - -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h - -test-sim-import-export: runsim - @echo "Running application import/export simulation. This may take several minutes..." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport - -test-sim-after-import: runsim - @echo "Running application simulation-after-import. This may take several minutes..." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport - -test-sim-custom-genesis-multi-seed: runsim - @echo "Running multi-seed custom genesis simulation..." - @echo "By default, ${HOME}/.zetacored/config/genesis.json will be used." - @$(BINDIR)/runsim -Genesis=${HOME}/.gaia/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation +test-sim-fullappsimulation: + @echo "Running TestFullAppSimulation." + @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Enabled=true \ + -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h test-sim-multi-seed-long: runsim @echo "Running long multi-seed application simulation. This may take awhile!" @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation @@ -44,34 +30,11 @@ test-sim-multi-seed-short: runsim @echo "Running short multi-seed application simulation. This may take awhile!" @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation -test-sim-benchmark-invariants: - @echo "Running simulation invariant benchmarks..." - @go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \ - -Enabled=true -NumBlocks=1000 -BlockSize=200 \ - -Period=1 -Commit=true -Seed=57 -v -timeout 24h + .PHONY: \ test-sim-nondeterminism \ -test-sim-custom-genesis-fast \ -test-sim-import-export \ -test-sim-after-import \ -test-sim-custom-genesis-multi-seed \ -test-sim-multi-seed-short \ +test-sim-fullappsimulation \ test-sim-multi-seed-long \ -test-sim-benchmark-invariants - -SIM_NUM_BLOCKS ?= 500 -SIM_BLOCK_SIZE ?= 200 -SIM_COMMIT ?= true - -test-sim-benchmark: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @go test -mod=readonly -benchmem -run=^$$ $(SIMAPP) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h - -test-sim-profile: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @go test -mod=readonly -benchmem -run=^$$ $(SIMAPP) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out +test-sim-multi-seed-short -.PHONY: test-sim-profile test-sim-benchmark \ No newline at end of file From ac8fddf9c7dd333d5c62d8ae293ce8acf00b35f8 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 20:35:56 +0530 Subject: [PATCH 05/22] move simulation tests to a separate directory --- app/modules.go | 44 +-------------------- sims.mk | 2 +- {app => tests/simulation}/sim/sim_config.go | 0 {app => tests/simulation}/sim/sim_state.go | 0 {app => tests/simulation}/sim/sim_utils.go | 0 {app => tests/simulation}/sim_test.go | 29 ++++++-------- 6 files changed, 16 insertions(+), 59 deletions(-) rename {app => tests/simulation}/sim/sim_config.go (100%) rename {app => tests/simulation}/sim/sim_state.go (100%) rename {app => tests/simulation}/sim/sim_utils.go (100%) rename {app => tests/simulation}/sim_test.go (88%) diff --git a/app/modules.go b/app/modules.go index 37151b717c..2d7fd82cb4 100644 --- a/app/modules.go +++ b/app/modules.go @@ -4,12 +4,10 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/auth" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" "github.com/cosmos/cosmos-sdk/x/bank" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -64,7 +62,7 @@ func simulationModules( _ bool, ) []module.AppModuleSimulation { return []module.AppModuleSimulation{ - auth.NewAppModule(appCodec, app.AccountKeeper, RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), //gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), @@ -84,41 +82,3 @@ func simulationModules( groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), } } - -// RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. -// It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. -func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts { - genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts)) - for i, acc := range simState.Accounts { - bacc := authtypes.NewBaseAccountWithAddress(acc.Address) - - // Only consider making a vesting account once the initial bonded validator - // set is exhausted due to needing to track DelegatedVesting. - if !(int64(i) > simState.NumBonded && simState.Rand.Intn(100) < 50) { - genesisAccs[i] = bacc - continue - } - - initialVesting := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, simState.Rand.Int63n(simState.InitialStake.Int64()))) - var endTime int64 - - startTime := simState.GenTimestamp.Unix() - - // Allow for some vesting accounts to vest very quickly while others very slowly. - if simState.Rand.Intn(100) < 50 { - endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime)+1, int(startTime+(60*60*24*30)))) - } else { - endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime)+1, int(startTime+(60*60*12)))) - } - - bva := vestingtypes.NewBaseVestingAccount(bacc, initialVesting, endTime) - - if simState.Rand.Intn(100) < 50 { - genesisAccs[i] = vestingtypes.NewContinuousVestingAccountRaw(bva, startTime) - } else { - genesisAccs[i] = vestingtypes.NewDelayedVestingAccountRaw(bva) - } - } - - return genesisAccs -} diff --git a/sims.mk b/sims.mk index fb8a11d6de..5ce445832b 100644 --- a/sims.mk +++ b/sims.mk @@ -4,7 +4,7 @@ ### Simulations BINDIR ?= $(GOPATH)/bin -SIMAPP = ./app +SIMAPP = ./tests/simulation runsim: $(BINDIR)/runsim $(BINDIR)/runsim: diff --git a/app/sim/sim_config.go b/tests/simulation/sim/sim_config.go similarity index 100% rename from app/sim/sim_config.go rename to tests/simulation/sim/sim_config.go diff --git a/app/sim/sim_state.go b/tests/simulation/sim/sim_state.go similarity index 100% rename from app/sim/sim_state.go rename to tests/simulation/sim/sim_state.go diff --git a/app/sim/sim_utils.go b/tests/simulation/sim/sim_utils.go similarity index 100% rename from app/sim/sim_utils.go rename to tests/simulation/sim/sim_utils.go diff --git a/app/sim_test.go b/tests/simulation/sim_test.go similarity index 88% rename from app/sim_test.go rename to tests/simulation/sim_test.go index c13538f451..8fbd18d0db 100644 --- a/app/sim_test.go +++ b/tests/simulation/sim_test.go @@ -1,4 +1,4 @@ -package app_test +package simulation_test import ( "encoding/json" @@ -15,6 +15,7 @@ import ( evmante "github.com/zeta-chain/ethermint/app/ante" zetaapp "github.com/zeta-chain/node/app" "github.com/zeta-chain/node/app/ante" + sim2 "github.com/zeta-chain/node/tests/simulation/sim" dbm "github.com/cometbft/cometbft-db" @@ -27,16 +28,12 @@ import ( simulation2 "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" - - // "github.com/cosmos/gaia/v11/app/helpers" - // "github.com/cosmos/gaia/v11/app/params" - "github.com/zeta-chain/node/app/sim" ) // AppChainID hardcoded chainID for simulation func init() { - sim.GetSimulatorFlags() + sim2.GetSimulatorFlags() } const ( @@ -95,11 +92,11 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { // TODO: Make another test for the fuzzer itself, which just has noOp txs // and doesn't depend on the application. func TestAppStateDeterminism(t *testing.T) { - if !sim.FlagEnabledValue { + if !sim2.FlagEnabledValue { t.Skip("skipping application simulation") } - config := sim.NewConfigFromFlags() + config := sim2.NewConfigFromFlags() config.InitialBlockHeight = 1 config.ExportParamsPath = "" config.OnOperation = false @@ -116,7 +113,7 @@ func TestAppStateDeterminism(t *testing.T) { appHashList := make([]json.RawMessage, numTimesToRunPerSeed) appOptions := make(simtestutil.AppOptionsMap, 0) - appOptions[server.FlagInvCheckPeriod] = sim.FlagPeriodValue + appOptions[server.FlagInvCheckPeriod] = sim2.FlagPeriodValue for i := 0; i < numSeeds; i++ { if config.Seed == simcli.DefaultSeedValue { @@ -127,7 +124,7 @@ func TestAppStateDeterminism(t *testing.T) { for j := 0; j < numTimesToRunPerSeed; j++ { var logger log.Logger - if sim.FlagVerboseValue { + if sim2.FlagVerboseValue { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) } else { logger = log.NewNopLogger() @@ -151,7 +148,7 @@ func TestAppStateDeterminism(t *testing.T) { t, os.Stdout, app.BaseApp, - sim.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + sim2.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), blockedAddresses, @@ -161,7 +158,7 @@ func TestAppStateDeterminism(t *testing.T) { require.NoError(t, err) if config.Commit { - sim.PrintStats(db) + sim2.PrintStats(db) } appHash := app.LastCommitID().Hash @@ -178,13 +175,13 @@ func TestAppStateDeterminism(t *testing.T) { } func TestFullAppSimulation(t *testing.T) { - config := sim.NewConfigFromFlags() + config := sim2.NewConfigFromFlags() config.ChainID = SimAppChainID config.BlockMaxGas = SimBlockMaxGas config.DBBackend = "memdb" //config.ExportStatePath = "/Users/tanmay/.zetacored/simulation_state_export.json" - db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "mem-db", "Simulation", sim.FlagVerboseValue, sim.FlagEnabledValue) + db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "mem-db", "Simulation", sim2.FlagVerboseValue, sim2.FlagEnabledValue) if skip { t.Skip("skipping application simulation") } @@ -195,7 +192,7 @@ func TestFullAppSimulation(t *testing.T) { require.NoError(t, os.RemoveAll(dir)) }() appOptions := make(simtestutil.AppOptionsMap, 0) - appOptions[server.FlagInvCheckPeriod] = sim.FlagPeriodValue + appOptions[server.FlagInvCheckPeriod] = sim2.FlagPeriodValue app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) require.NoError(t, err) @@ -205,7 +202,7 @@ func TestFullAppSimulation(t *testing.T) { t, os.Stdout, app.BaseApp, - sim.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + sim2.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 simtestutil.SimulationOperations(app, app.AppCodec(), config), blockedAddresses, From b55f4396b50f71cdea641371da228a6517e6b233 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 21:40:59 +0530 Subject: [PATCH 06/22] remove unused functions --- tests/simulation/sim/sim_utils.go | 64 +------------------------------ tests/simulation/sim_test.go | 57 ++++++++++++++------------- 2 files changed, 31 insertions(+), 90 deletions(-) diff --git a/tests/simulation/sim/sim_utils.go b/tests/simulation/sim/sim_utils.go index da915257f9..a54af7164a 100644 --- a/tests/simulation/sim/sim_utils.go +++ b/tests/simulation/sim/sim_utils.go @@ -1,76 +1,14 @@ package sim import ( - "encoding/json" "fmt" - "os" dbm "github.com/cometbft/cometbft-db" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - - zetaapp "github.com/zeta-chain/node/app" ) -// SimulationOperations retrieves the simulation params from the provided file path -// and returns all the modules weighted operations -func SimulationOperations(app *zetaapp.App, cdc codec.JSONCodec, config simtypes.Config) []simtypes.WeightedOperation { - simState := module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - } - - if config.ParamsFile != "" { - bz, err := os.ReadFile(config.ParamsFile) - if err != nil { - panic(err) - } - - err = json.Unmarshal(bz, &simState.AppParams) - if err != nil { - panic(err) - } - } - - simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck - simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState) - return app.SimulationManager().WeightedOperations(simState) -} - -// CheckExportSimulation exports the app state and simulation parameters to JSON -// if the export paths are defined. -func CheckExportSimulation(app runtime.AppI, config simtypes.Config, params simtypes.Params) error { - if config.ExportStatePath != "" { - fmt.Println("exporting app state...") - exported, err := app.ExportAppStateAndValidators(false, nil, nil) - if err != nil { - return err - } - - if err := os.WriteFile(config.ExportStatePath, []byte(exported.AppState), 0o600); err != nil { - return err - } - } - - if config.ExportParamsPath != "" { - fmt.Println("exporting simulation params...") - paramsBz, err := json.MarshalIndent(params, "", " ") - if err != nil { - return err - } - - if err := os.WriteFile(config.ExportParamsPath, paramsBz, 0o600); err != nil { - return err - } - } - return nil -} - // PrintStats prints the corresponding statistics from the app DB. func PrintStats(db dbm.DB) { - fmt.Println("\nLevelDB Stats") + fmt.Println("\nDB Stats") fmt.Println(db.Stats()["leveldb.stats"]) fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) } diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 8fbd18d0db..934f57b82f 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -15,7 +15,7 @@ import ( evmante "github.com/zeta-chain/ethermint/app/ante" zetaapp "github.com/zeta-chain/node/app" "github.com/zeta-chain/node/app/ante" - sim2 "github.com/zeta-chain/node/tests/simulation/sim" + simutils "github.com/zeta-chain/node/tests/simulation/sim" dbm "github.com/cometbft/cometbft-db" @@ -24,16 +24,16 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - simulation2 "github.com/cosmos/cosmos-sdk/types/simulation" + cosmossimutils "github.com/cosmos/cosmos-sdk/testutil/sims" + cosmossim "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" - simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + cosmossimcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" ) // AppChainID hardcoded chainID for simulation func init() { - sim2.GetSimulatorFlags() + simutils.GetSimulatorFlags() } const ( @@ -92,31 +92,32 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { // TODO: Make another test for the fuzzer itself, which just has noOp txs // and doesn't depend on the application. func TestAppStateDeterminism(t *testing.T) { - if !sim2.FlagEnabledValue { + if !simutils.FlagEnabledValue { t.Skip("skipping application simulation") } - config := sim2.NewConfigFromFlags() + config := simutils.NewConfigFromFlags() config.InitialBlockHeight = 1 config.ExportParamsPath = "" config.OnOperation = false config.AllInvariants = false config.ChainID = SimAppChainID + config.DBBackend = "goleveldb" numSeeds := 3 numTimesToRunPerSeed := 5 // We will be overriding the random seed and just run a single simulation on the provided seed value - if config.Seed != simcli.DefaultSeedValue { + if config.Seed != cosmossimcli.DefaultSeedValue { numSeeds = 1 } appHashList := make([]json.RawMessage, numTimesToRunPerSeed) - appOptions := make(simtestutil.AppOptionsMap, 0) - appOptions[server.FlagInvCheckPeriod] = sim2.FlagPeriodValue + appOptions := make(cosmossimutils.AppOptionsMap, 0) + appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue for i := 0; i < numSeeds; i++ { - if config.Seed == simcli.DefaultSeedValue { + if config.Seed == cosmossimcli.DefaultSeedValue { config.Seed = rand.Int63() } @@ -124,14 +125,16 @@ func TestAppStateDeterminism(t *testing.T) { for j := 0; j < numTimesToRunPerSeed; j++ { var logger log.Logger - if sim2.FlagVerboseValue { + if simutils.FlagVerboseValue { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) } else { logger = log.NewNopLogger() } - db := dbm.NewMemDB() - dir, err := os.MkdirTemp("", "zeta-simulation") + db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, "level-db", "Simulation", simutils.FlagVerboseValue, simutils.FlagEnabledValue) + if skip { + t.Skip("skipping application simulation") + } require.NoError(t, err) appOptions[flags.FlagHome] = dir @@ -148,9 +151,9 @@ func TestAppStateDeterminism(t *testing.T) { t, os.Stdout, app.BaseApp, - sim2.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), - simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(app, app.AppCodec(), config), + simutils.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + cosmossim.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + cosmossimutils.SimulationOperations(app, app.AppCodec(), config), blockedAddresses, config, app.AppCodec(), @@ -158,7 +161,7 @@ func TestAppStateDeterminism(t *testing.T) { require.NoError(t, err) if config.Commit { - sim2.PrintStats(db) + simutils.PrintStats(db) } appHash := app.LastCommitID().Hash @@ -175,13 +178,13 @@ func TestAppStateDeterminism(t *testing.T) { } func TestFullAppSimulation(t *testing.T) { - config := sim2.NewConfigFromFlags() + config := simutils.NewConfigFromFlags() config.ChainID = SimAppChainID config.BlockMaxGas = SimBlockMaxGas - config.DBBackend = "memdb" + config.DBBackend = "goleveldb" //config.ExportStatePath = "/Users/tanmay/.zetacored/simulation_state_export.json" - db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "mem-db", "Simulation", sim2.FlagVerboseValue, sim2.FlagEnabledValue) + db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, "level-db", "Simulation", simutils.FlagVerboseValue, simutils.FlagEnabledValue) if skip { t.Skip("skipping application simulation") } @@ -191,8 +194,8 @@ func TestFullAppSimulation(t *testing.T) { require.NoError(t, db.Close()) require.NoError(t, os.RemoveAll(dir)) }() - appOptions := make(simtestutil.AppOptionsMap, 0) - appOptions[server.FlagInvCheckPeriod] = sim2.FlagPeriodValue + appOptions := make(cosmossimutils.AppOptionsMap, 0) + appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) require.NoError(t, err) @@ -202,9 +205,9 @@ func TestFullAppSimulation(t *testing.T) { t, os.Stdout, app.BaseApp, - sim2.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), - simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(app, app.AppCodec(), config), + simutils.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + cosmossim.RandomAccounts, + cosmossimutils.SimulationOperations(app, app.AppCodec(), config), blockedAddresses, config, app.AppCodec(), @@ -216,6 +219,6 @@ func TestFullAppSimulation(t *testing.T) { require.NoError(t, err) if config.Commit { - simtestutil.PrintStats(db) + cosmossimutils.PrintStats(db) } } From 913aa19802d558565ab4d2a412f4eba47c18d3f9 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 2 Oct 2024 17:11:05 +0530 Subject: [PATCH 07/22] add comments --- sims.mk | 7 +- tests/simulation/sim/sim_state.go | 5 +- tests/simulation/sim_test.go | 111 +++++++------- testutil/simapp/default_constants.go | 25 --- testutil/simapp/simapp.go | 219 --------------------------- 5 files changed, 66 insertions(+), 301 deletions(-) delete mode 100644 testutil/simapp/default_constants.go delete mode 100644 testutil/simapp/simapp.go diff --git a/sims.mk b/sims.mk index 5ce445832b..65301e0e9e 100644 --- a/sims.mk +++ b/sims.mk @@ -6,6 +6,8 @@ BINDIR ?= $(GOPATH)/bin SIMAPP = ./tests/simulation + +# Run sim is a cosmos tool which helps us to run multiple simulations in parallel. runsim: $(BINDIR)/runsim $(BINDIR)/runsim: @echo "Installing runsim..." @@ -15,13 +17,14 @@ $(BINDIR)/runsim: test-sim-nondeterminism: @echo "Running non-determinism test..." @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ - -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h + -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h test-sim-fullappsimulation: @echo "Running TestFullAppSimulation." @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Enabled=true \ - -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h + -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + test-sim-multi-seed-long: runsim @echo "Running long multi-seed application simulation. This may take awhile!" @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation diff --git a/tests/simulation/sim/sim_state.go b/tests/simulation/sim/sim_state.go index 12df57dc5c..8b4d73a0c6 100644 --- a/tests/simulation/sim/sim_state.go +++ b/tests/simulation/sim/sim_state.go @@ -107,9 +107,9 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt notBondedTokens = notBondedTokens.Add(val.GetTokens()) } notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) + // edit bank state to make it have the not bonded pool tokens bankStateBz, ok := rawState[banktypes.ModuleName] - // TODO(fdymylja/jonathan): should we panic in this case if !ok { panic("bank genesis state is missing") } @@ -134,6 +134,7 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt }) } + // Set the bond denom in the EVM genesis state evmStateBz, ok := rawState[evmtypes.ModuleName] if !ok { panic("evm genesis state is missing") @@ -207,8 +208,6 @@ func AppStateRandomizedFn( GenTimestamp: genesisTimestamp, } - fmt.Println("Generating genesis states...") - simManager.GenerateGenesisStates(simState) appState, err := json.Marshal(genesisState) diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 934f57b82f..4efb6a1646 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -39,14 +39,16 @@ func init() { const ( SimAppChainID = "simulation_777-1" SimBlockMaxGas = 815000000 - TestAppChainID = "zetachain_777-1" + SimDBBackend = "goleveldb" + SimDBName = "simulation" ) -// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail. func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) (*zetaapp.App, error) { encCdc := zetaapp.MakeEncodingConfig() - app := zetaapp.New( + + // Set load latest version to false as we manually set it later. + zetaApp := zetaapp.New( logger, db, nil, @@ -58,17 +60,20 @@ func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, appOptions, baseAppOptions..., ) + + // Set power reduction to 1 to make sure all bonded validators are added to the validator set sdk.DefaultPowerReduction = sdk.OneInt() - // disable feemarket on native tx + + // use zeta antehandler options := ante.HandlerOptions{ - AccountKeeper: app.AccountKeeper, - BankKeeper: app.BankKeeper, - EvmKeeper: app.EvmKeeper, - FeeMarketKeeper: app.FeeMarketKeeper, + AccountKeeper: zetaApp.AccountKeeper, + BankKeeper: zetaApp.BankKeeper, + EvmKeeper: zetaApp.EvmKeeper, + FeeMarketKeeper: zetaApp.FeeMarketKeeper, SignModeHandler: encCdc.TxConfig.SignModeHandler(), SigGasConsumer: evmante.DefaultSigVerificationGasConsumer, MaxTxGasWanted: 0, - ObserverKeeper: app.ObserverKeeper, + ObserverKeeper: zetaApp.ObserverKeeper, } anteHandler, err := ante.NewAnteHandler(options) @@ -76,11 +81,11 @@ func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, panic(err) } - app.SetAnteHandler(anteHandler) - if err := app.LoadLatestVersion(); err != nil { + zetaApp.SetAnteHandler(anteHandler) + if err := zetaApp.LoadLatestVersion(); err != nil { return nil, err } - return app, nil + return zetaApp, nil } // interBlockCacheOpt returns a BaseApp option function that sets the persistent @@ -89,20 +94,24 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) } -// TODO: Make another test for the fuzzer itself, which just has noOp txs -// and doesn't depend on the application. +// TestAppStateDeterminism runs a full application simulation , and produces multiple blocks as per the config +// It checks the determinism of the application by comparing the apphash at the end of each run to other runs +// The following test certifies that , for the same set of operations ( irrespective of what the operations are ) , +// we would reach the same final state func TestAppStateDeterminism(t *testing.T) { if !simutils.FlagEnabledValue { t.Skip("skipping application simulation") } config := simutils.NewConfigFromFlags() + config.InitialBlockHeight = 1 config.ExportParamsPath = "" config.OnOperation = false config.AllInvariants = false config.ChainID = SimAppChainID - config.DBBackend = "goleveldb" + config.DBBackend = SimDBBackend + config.BlockMaxGas = SimBlockMaxGas numSeeds := 3 numTimesToRunPerSeed := 5 @@ -112,59 +121,51 @@ func TestAppStateDeterminism(t *testing.T) { numSeeds = 1 } + // For the same seed, the app hash produced at the end of each run should be the same appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + appOptions := make(cosmossimutils.AppOptionsMap, 0) appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue + fmt.Println("Running tests for numSeeds: ", numSeeds, " numTimesToRunPerSeed: ", numTimesToRunPerSeed) + for i := 0; i < numSeeds; i++ { if config.Seed == cosmossimcli.DefaultSeedValue { config.Seed = rand.Int63() } - fmt.Println("config.Seed: ", config.Seed) - + //dbPrefix := fmt.Sprintf("%s-%d", SimDBBackend, i) + // For the same seed, the app hash produced at the end of each run should be the same for j := 0; j < numTimesToRunPerSeed; j++ { - var logger log.Logger - if simutils.FlagVerboseValue { - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - } else { - logger = log.NewNopLogger() - } - - db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, "level-db", "Simulation", simutils.FlagVerboseValue, simutils.FlagEnabledValue) - if skip { - t.Skip("skipping application simulation") - } + db, dir, logger, _, err := cosmossimutils.SetupSimulation(config, SimDBBackend, SimDBName, simutils.FlagVerboseValue, simutils.FlagEnabledValue) require.NoError(t, err) appOptions[flags.FlagHome] = dir - app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + simApp, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) fmt.Printf( "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, ) - blockedAddresses := app.ModuleAccountAddrs() + blockedAddresses := simApp.ModuleAccountAddrs() _, _, err = simulation.SimulateFromSeed( t, os.Stdout, - app.BaseApp, - simutils.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), - cosmossim.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - cosmossimutils.SimulationOperations(app, app.AppCodec(), config), + simApp.BaseApp, + simutils.AppStateFn(simApp.AppCodec(), simApp.SimulationManager(), simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec())), + cosmossim.RandomAccounts, + cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), blockedAddresses, config, - app.AppCodec(), + simApp.AppCodec(), ) require.NoError(t, err) - if config.Commit { - simutils.PrintStats(db) - } + simutils.PrintStats(db) - appHash := app.LastCommitID().Hash + appHash := simApp.LastCommitID().Hash appHashList[j] = appHash if j != 0 { @@ -177,14 +178,17 @@ func TestAppStateDeterminism(t *testing.T) { } } +// TestFullAppSimulation runs a full app simulation with the provided configuration. +// At the end of the run it tries to export the genesis state to make sure the export works. func TestFullAppSimulation(t *testing.T) { + config := simutils.NewConfigFromFlags() + config.ChainID = SimAppChainID config.BlockMaxGas = SimBlockMaxGas - config.DBBackend = "goleveldb" - //config.ExportStatePath = "/Users/tanmay/.zetacored/simulation_state_export.json" + config.DBBackend = SimDBBackend - db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, "level-db", "Simulation", simutils.FlagVerboseValue, simutils.FlagEnabledValue) + db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, SimDBBackend, SimDBName, simutils.FlagVerboseValue, simutils.FlagEnabledValue) if skip { t.Skip("skipping application simulation") } @@ -196,29 +200,32 @@ func TestFullAppSimulation(t *testing.T) { }() appOptions := make(cosmossimutils.AppOptionsMap, 0) appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue + appOptions[flags.FlagHome] = dir - app, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + simApp, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) require.NoError(t, err) - blockedAddresses := app.ModuleAccountAddrs() + blockedAddresses := simApp.ModuleAccountAddrs() _, _, simerr := simulation.SimulateFromSeed( t, os.Stdout, - app.BaseApp, - simutils.AppStateFn(app.AppCodec(), app.SimulationManager(), app.ModuleBasics.DefaultGenesis(app.AppCodec())), + simApp.BaseApp, + simutils.AppStateFn(simApp.AppCodec(), simApp.SimulationManager(), simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec())), cosmossim.RandomAccounts, - cosmossimutils.SimulationOperations(app, app.AppCodec(), config), + cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), blockedAddresses, config, - app.AppCodec(), + simApp.AppCodec(), ) require.NoError(t, simerr) // check export works as expected - _, err = app.ExportAppStateAndValidators(false, nil, nil) + exported, err := simApp.ExportAppStateAndValidators(false, nil, nil) require.NoError(t, err) - - if config.Commit { - cosmossimutils.PrintStats(db) + if config.ExportStatePath != "" { + err := os.WriteFile(config.ExportStatePath, exported.AppState, 0o600) + require.NoError(t, err) } + + cosmossimutils.PrintStats(db) } diff --git a/testutil/simapp/default_constants.go b/testutil/simapp/default_constants.go deleted file mode 100644 index c4398ad7bb..0000000000 --- a/testutil/simapp/default_constants.go +++ /dev/null @@ -1,25 +0,0 @@ -package simapp - -import ( - "time" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmtypes "github.com/cometbft/cometbft/types" -) - -var defaultConsensusParams = &tmproto.ConsensusParams{ - Block: &tmproto.BlockParams{ - MaxBytes: 200000, - MaxGas: 2000000, - }, - Evidence: &tmproto.EvidenceParams{ - MaxAgeNumBlocks: 302400, - MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration - MaxBytes: 10000, - }, - Validator: &tmproto.ValidatorParams{ - PubKeyTypes: []string{ - tmtypes.ABCIPubKeyTypeEd25519, - }, - }, -} diff --git a/testutil/simapp/simapp.go b/testutil/simapp/simapp.go deleted file mode 100644 index b42b0b5f1a..0000000000 --- a/testutil/simapp/simapp.go +++ /dev/null @@ -1,219 +0,0 @@ -package simapp - -import ( - "encoding/json" - "testing" - "time" - - tmdb "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/log" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmtypes "github.com/cometbft/cometbft/types" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/stretchr/testify/require" - - "github.com/zeta-chain/node/app" - "github.com/zeta-chain/node/cmd/zetacored/config" - types2 "github.com/zeta-chain/node/x/emissions/types" -) - -func Setup(isCheckTx bool) *app.App { - app, genesisState := setup(!isCheckTx, 5) - if !isCheckTx { - // init chain must be called to stop deliverState from being nil - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - if err != nil { - panic(err) - } - - // Initialize the chain - app.InitChain( - abci.RequestInitChain{ - ChainId: "simnet_101-1", - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: defaultConsensusParams, - AppStateBytes: stateBytes, - }, - ) - } - - return app -} - -func setup(withGenesis bool, invCheckPeriod uint) (*app.App, app.GenesisState) { - db := tmdb.NewMemDB() - encCdc := app.MakeEncodingConfig() - a := app.New( - log.NewNopLogger(), - db, - nil, - true, - map[int64]bool{}, - app.DefaultNodeHome, - invCheckPeriod, - encCdc, - simtestutil.EmptyAppOptions{}, - ) - if withGenesis { - return a, app.NewDefaultGenesisState(encCdc.Codec) - } - return a, app.GenesisState{} -} - -func SetupWithGenesisValSet( - t *testing.T, - valSet *tmtypes.ValidatorSet, - genDelAccs []authtypes.GenesisAccount, - bondAmt sdk.Int, - emissionParams types2.Params, - genDelBalances []banktypes.Balance, - genBalances []banktypes.Balance, -) *app.App { - app, genesisState := setup(true, 5) - // set genesis accounts - authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genDelAccs) - genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) - - validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) - delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - // Make all members of valSet as validators - // Make all members of delSet as delegators to each of the validators - for _, val := range valSet.Validators { - pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) - require.NoError(t, err) - pkAny, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) - validator := stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(val.Address).String(), - ConsensusPubkey: pkAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: bondAmt, - DelegatorShares: sdk.OneDec(), - Description: stakingtypes.Description{}, - UnbondingHeight: int64(0), - UnbondingTime: time.Unix(0, 0).UTC(), - Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), - MinSelfDelegation: sdk.ZeroInt(), - } - validators = append(validators, validator) - delegations = append( - delegations, - stakingtypes.NewDelegation(genDelAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()), - ) - } - - emissionsGenesis := types2.DefaultGenesis() - emissionsGenesis.Params = emissionParams - genesisState[types2.ModuleName] = app.AppCodec().MustMarshalJSON(emissionsGenesis) - // set validators and delegations - params := stakingtypes.DefaultParams() - params.BondDenom = config.BaseDenom - stakingGenesis := stakingtypes.NewGenesisState(params, validators, delegations) - genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) - - totalSupply := sdk.NewCoins() - // genDelBalances contains additional balances for delegators - // Add Bond amount and additional coins for these addresses - - for _, b := range genDelBalances { - // add genesis acc tokens and delegated tokens to total supply - totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(config.BaseDenom, bondAmt))...) - } - // add balances for non delegator accounts - // Add only external balances - for _, b := range genBalances { - // add genesis acc tokens and delegated tokens to total supply - totalSupply = totalSupply.Add(b.Coins...) - } - - totalBalances := []banktypes.Balance{} - // Add extra balance to account for delegator bonded pool - totalBalances = append(append(append(totalBalances, genBalances...), genDelBalances...), banktypes.Balance{ - Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(config.BaseDenom, bondAmt)}, - }) - - // update total supply - - bankGenesis := banktypes.NewGenesisState( - banktypes.DefaultGenesisState().Params, - totalBalances, - totalSupply, - []banktypes.Metadata{}, - []banktypes.SendEnabled{}, - ) - genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) - - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - require.NoError(t, err) - - // init chain will set the validator set and initialize the genesis accounts - app.InitChain( - abci.RequestInitChain{ - ChainId: "simnet_101-1", - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: defaultConsensusParams, - AppStateBytes: stateBytes, - }, - ) - - // commit genesis changes - app.Commit() - - app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ - Height: app.LastBlockHeight() + 1, - AppHash: app.LastCommitID().Hash, - ValidatorsHash: valSet.Hash(), - NextValidatorsHash: valSet.Hash(), - ChainID: "simnet_101-1", - }}) - - return app -} - -func SetupWithGenesisAccounts(genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *app.App { - app, genesisState := setup(true, 0) - authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) - genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) - - totalSupply := sdk.NewCoins() - for _, b := range balances { - totalSupply = totalSupply.Add(b.Coins...) - } - - bankGenesis := banktypes.NewGenesisState( - banktypes.DefaultGenesisState().Params, - balances, - totalSupply, - []banktypes.Metadata{}, - []banktypes.SendEnabled{}, - ) - genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) - - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - if err != nil { - panic(err) - } - - app.InitChain( - abci.RequestInitChain{ - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: defaultConsensusParams, - AppStateBytes: stateBytes, - }, - ) - - app.Commit() - - app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1}}) - - return app -} From 10d8a38ef9d4b8022761aad6f0f9dfef03d00660 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 2 Oct 2024 19:53:41 +0530 Subject: [PATCH 08/22] enable gov module --- app/modules.go | 2 +- sims.mk | 2 +- tests/simulation/sim/sim_state.go | 3 ++ tests/simulation/sim/sim_utils.go | 49 +++++++++++++++++++++++ tests/simulation/sim_test.go | 64 ++----------------------------- 5 files changed, 58 insertions(+), 62 deletions(-) diff --git a/app/modules.go b/app/modules.go index 2d7fd82cb4..a2a6a90200 100644 --- a/app/modules.go +++ b/app/modules.go @@ -64,7 +64,7 @@ func simulationModules( return []module.AppModuleSimulation{ auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - //gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), + gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), slashing.NewAppModule( diff --git a/sims.mk b/sims.mk index 65301e0e9e..db4b4d7a5c 100644 --- a/sims.mk +++ b/sims.mk @@ -17,7 +17,7 @@ $(BINDIR)/runsim: test-sim-nondeterminism: @echo "Running non-determinism test..." @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ - -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h test-sim-fullappsimulation: diff --git a/tests/simulation/sim/sim_state.go b/tests/simulation/sim/sim_state.go index 8b4d73a0c6..c4f884b9b4 100644 --- a/tests/simulation/sim/sim_state.go +++ b/tests/simulation/sim/sim_state.go @@ -188,6 +188,9 @@ func AppStateRandomizedFn( numInitiallyBonded = numAccs } + // Set the default power reduction to be one less than the initial stake so that all randomised validators are part of the validator set + sdk.DefaultPowerReduction = initialStake.Sub(sdk.OneInt()) + fmt.Printf( `Selected randomly generated parameters for simulated genesis: { diff --git a/tests/simulation/sim/sim_utils.go b/tests/simulation/sim/sim_utils.go index a54af7164a..56a73f17af 100644 --- a/tests/simulation/sim/sim_utils.go +++ b/tests/simulation/sim/sim_utils.go @@ -4,8 +4,57 @@ import ( "fmt" dbm "github.com/cometbft/cometbft-db" + "github.com/cometbft/cometbft/libs/log" + "github.com/cosmos/cosmos-sdk/baseapp" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/zeta-chain/ethermint/app" + evmante "github.com/zeta-chain/ethermint/app/ante" + zetaapp "github.com/zeta-chain/node/app" + "github.com/zeta-chain/node/app/ante" ) +func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) (*zetaapp.App, error) { + + encCdc := zetaapp.MakeEncodingConfig() + + // Set load latest version to false as we manually set it later. + zetaApp := zetaapp.New( + logger, + db, + nil, + false, + map[int64]bool{}, + app.DefaultNodeHome, + 5, + encCdc, + appOptions, + baseAppOptions..., + ) + + // use zeta antehandler + options := ante.HandlerOptions{ + AccountKeeper: zetaApp.AccountKeeper, + BankKeeper: zetaApp.BankKeeper, + EvmKeeper: zetaApp.EvmKeeper, + FeeMarketKeeper: zetaApp.FeeMarketKeeper, + SignModeHandler: encCdc.TxConfig.SignModeHandler(), + SigGasConsumer: evmante.DefaultSigVerificationGasConsumer, + MaxTxGasWanted: 0, + ObserverKeeper: zetaApp.ObserverKeeper, + } + + anteHandler, err := ante.NewAnteHandler(options) + if err != nil { + panic(err) + } + + zetaApp.SetAnteHandler(anteHandler) + if err := zetaApp.LoadLatestVersion(); err != nil { + return nil, err + } + return zetaApp, nil +} + // PrintStats prints the corresponding statistics from the app DB. func PrintStats(db dbm.DB) { fmt.Println("\nDB Stats") diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 4efb6a1646..a7fb801b9d 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -7,18 +7,9 @@ import ( "os" "testing" - "github.com/cometbft/cometbft/libs/log" - servertypes "github.com/cosmos/cosmos-sdk/server/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" - "github.com/zeta-chain/ethermint/app" - evmante "github.com/zeta-chain/ethermint/app/ante" - zetaapp "github.com/zeta-chain/node/app" - "github.com/zeta-chain/node/app/ante" simutils "github.com/zeta-chain/node/tests/simulation/sim" - dbm "github.com/cometbft/cometbft-db" - "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/baseapp" @@ -43,51 +34,6 @@ const ( SimDBName = "simulation" ) -func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) (*zetaapp.App, error) { - - encCdc := zetaapp.MakeEncodingConfig() - - // Set load latest version to false as we manually set it later. - zetaApp := zetaapp.New( - logger, - db, - nil, - false, - map[int64]bool{}, - app.DefaultNodeHome, - 5, - encCdc, - appOptions, - baseAppOptions..., - ) - - // Set power reduction to 1 to make sure all bonded validators are added to the validator set - sdk.DefaultPowerReduction = sdk.OneInt() - - // use zeta antehandler - options := ante.HandlerOptions{ - AccountKeeper: zetaApp.AccountKeeper, - BankKeeper: zetaApp.BankKeeper, - EvmKeeper: zetaApp.EvmKeeper, - FeeMarketKeeper: zetaApp.FeeMarketKeeper, - SignModeHandler: encCdc.TxConfig.SignModeHandler(), - SigGasConsumer: evmante.DefaultSigVerificationGasConsumer, - MaxTxGasWanted: 0, - ObserverKeeper: zetaApp.ObserverKeeper, - } - - anteHandler, err := ante.NewAnteHandler(options) - if err != nil { - panic(err) - } - - zetaApp.SetAnteHandler(anteHandler) - if err := zetaApp.LoadLatestVersion(); err != nil { - return nil, err - } - return zetaApp, nil -} - // interBlockCacheOpt returns a BaseApp option function that sets the persistent // inter-block write-through cache. func interBlockCacheOpt() func(*baseapp.BaseApp) { @@ -97,7 +43,7 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { // TestAppStateDeterminism runs a full application simulation , and produces multiple blocks as per the config // It checks the determinism of the application by comparing the apphash at the end of each run to other runs // The following test certifies that , for the same set of operations ( irrespective of what the operations are ) , -// we would reach the same final state +// we would reach the same final state if the initital state is the same func TestAppStateDeterminism(t *testing.T) { if !simutils.FlagEnabledValue { t.Skip("skipping application simulation") @@ -121,7 +67,6 @@ func TestAppStateDeterminism(t *testing.T) { numSeeds = 1 } - // For the same seed, the app hash produced at the end of each run should be the same appHashList := make([]json.RawMessage, numTimesToRunPerSeed) appOptions := make(cosmossimutils.AppOptionsMap, 0) @@ -133,15 +78,13 @@ func TestAppStateDeterminism(t *testing.T) { if config.Seed == cosmossimcli.DefaultSeedValue { config.Seed = rand.Int63() } - - //dbPrefix := fmt.Sprintf("%s-%d", SimDBBackend, i) // For the same seed, the app hash produced at the end of each run should be the same for j := 0; j < numTimesToRunPerSeed; j++ { db, dir, logger, _, err := cosmossimutils.SetupSimulation(config, SimDBBackend, SimDBName, simutils.FlagVerboseValue, simutils.FlagEnabledValue) require.NoError(t, err) appOptions[flags.FlagHome] = dir - simApp, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + simApp, err := simutils.NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) fmt.Printf( "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", @@ -150,6 +93,7 @@ func TestAppStateDeterminism(t *testing.T) { blockedAddresses := simApp.ModuleAccountAddrs() + // Random seed is used to produce a random initial state for the simulation _, _, err = simulation.SimulateFromSeed( t, os.Stdout, @@ -202,7 +146,7 @@ func TestFullAppSimulation(t *testing.T) { appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue appOptions[flags.FlagHome] = dir - simApp, err := NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + simApp, err := simutils.NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) require.NoError(t, err) blockedAddresses := simApp.ModuleAccountAddrs() From 49d430cf725f9235ce037c169b12f3f2ad63de0d Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 2 Oct 2024 19:57:05 +0530 Subject: [PATCH 09/22] enable gov module --- tests/simulation/sim/sim_utils.go | 2 +- tests/simulation/sim_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/simulation/sim/sim_utils.go b/tests/simulation/sim/sim_utils.go index 56a73f17af..a1e25fb8d7 100644 --- a/tests/simulation/sim/sim_utils.go +++ b/tests/simulation/sim/sim_utils.go @@ -59,5 +59,5 @@ func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, func PrintStats(db dbm.DB) { fmt.Println("\nDB Stats") fmt.Println(db.Stats()["leveldb.stats"]) - fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) + fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"]) } diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index a7fb801b9d..ffb48f1f95 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -171,5 +171,5 @@ func TestFullAppSimulation(t *testing.T) { require.NoError(t, err) } - cosmossimutils.PrintStats(db) + simutils.PrintStats(db) } From 73fbcf5d21156881a6a0912c37e0458e11fac893 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 2 Oct 2024 22:01:31 +0530 Subject: [PATCH 10/22] fix lint error --- app/encoding.go | 1 + app/modules.go | 34 +++++++++++++++--- changelog.md | 1 + e2e/runner/admin_evm.go | 6 ++-- e2e/runner/report.go | 2 +- tests/simulation/sim/sim_config.go | 56 +++++++++++++++++++++++++----- tests/simulation/sim/sim_state.go | 32 ++++++++++++++--- tests/simulation/sim/sim_utils.go | 9 +++-- tests/simulation/sim_test.go | 47 +++++++++++++++++++++---- 9 files changed, 157 insertions(+), 31 deletions(-) diff --git a/app/encoding.go b/app/encoding.go index dbf32a0878..2e8c728b0f 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -14,6 +14,7 @@ import ( evmenc "github.com/zeta-chain/ethermint/encoding" ethermint "github.com/zeta-chain/ethermint/types" evmtypes "github.com/zeta-chain/ethermint/x/evm/types" + authoritytypes "github.com/zeta-chain/node/x/authority/types" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" emissionstypes "github.com/zeta-chain/node/x/emissions/types" diff --git a/app/modules.go b/app/modules.go index a2a6a90200..c94872305b 100644 --- a/app/modules.go +++ b/app/modules.go @@ -32,7 +32,7 @@ import ( // non-dependant module elements, such as codec registration // and genesis verification. func newBasicManagerFromManager(app *App) module.BasicManager { - var moduleBasics []module.AppModuleBasic + moduleBasics := make([]module.AppModuleBasic, 0) for _, m := range app.mm.Modules { m, ok := m.(module.AppModuleBasic) if !ok { @@ -62,11 +62,35 @@ func simulationModules( _ bool, ) []module.AppModuleSimulation { return []module.AppModuleSimulation{ - auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), + auth.NewAppModule( + appCodec, + app.AccountKeeper, + authsims.RandomGenesisAccounts, + app.GetSubspace(authtypes.ModuleName), + ), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), + gov.NewAppModule( + appCodec, + &app.GovKeeper, + app.AccountKeeper, + app.BankKeeper, + app.GetSubspace(govtypes.ModuleName), + ), + staking.NewAppModule( + appCodec, + app.StakingKeeper, + app.AccountKeeper, + app.BankKeeper, + app.GetSubspace(stakingtypes.ModuleName), + ), + distr.NewAppModule( + appCodec, + app.DistrKeeper, + app.AccountKeeper, + app.BankKeeper, + app.StakingKeeper, + app.GetSubspace(distrtypes.ModuleName), + ), slashing.NewAppModule( appCodec, app.SlashingKeeper, diff --git a/changelog.md b/changelog.md index d78c1861ae..6069bac909 100644 --- a/changelog.md +++ b/changelog.md @@ -36,6 +36,7 @@ * [2874](https://github.com/zeta-chain/node/pull/2874) - add support for multiple runs for precompile tests * [2895](https://github.com/zeta-chain/node/pull/2895) - add e2e test for bitcoin deposit and call * [2894](https://github.com/zeta-chain/node/pull/2894) - increase gas limit for TSS vote tx +* [2947](https://github.com/zeta-chain/node/pull/2947/) - add simulation tests ### Fixes diff --git a/e2e/runner/admin_evm.go b/e2e/runner/admin_evm.go index a373f2325a..ed3f682d0b 100644 --- a/e2e/runner/admin_evm.go +++ b/e2e/runner/admin_evm.go @@ -1,8 +1,6 @@ package runner import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/require" @@ -14,7 +12,7 @@ func (r *E2ERunner) UpdateTssAddressForConnector() { tx, err := r.ConnectorEth.UpdateTssAddress(r.EVMAuth, r.TSSAddress) require.NoError(r, err) - r.Logger.Info(fmt.Sprintf("TSS Address Update Tx: %s", tx.Hash().String())) + r.Logger.Info("TSS Address Update Tx: %s", tx.Hash().String()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) utils.RequireTxSuccessful(r, receipt) @@ -28,7 +26,7 @@ func (r *E2ERunner) UpdateTssAddressForErc20custody() { tx, err := r.ERC20Custody.UpdateTSSAddress(r.EVMAuth, r.TSSAddress) require.NoError(r, err) - r.Logger.Info(fmt.Sprintf("TSS ERC20 Address Update Tx: %s", tx.Hash().String())) + r.Logger.Info("TSS ERC20 Address Update Tx: %s", tx.Hash().String()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) utils.RequireTxSuccessful(r, receipt) diff --git a/e2e/runner/report.go b/e2e/runner/report.go index c860f014b1..b36e3033bc 100644 --- a/e2e/runner/report.go +++ b/e2e/runner/report.go @@ -59,7 +59,7 @@ func (r *E2ERunner) PrintTestReports(tr TestReports) { if err != nil { r.Logger.Print("Error rendering test report: %s", err) } - r.Logger.PrintNoPrefix(table) + r.Logger.PrintNoPrefix("%s", table) } // NetworkReport is a struct that contains the report for the network used after running e2e tests diff --git a/tests/simulation/sim/sim_config.go b/tests/simulation/sim/sim_config.go index 43c150303e..98d2ffb6d9 100644 --- a/tests/simulation/sim/sim_config.go +++ b/tests/simulation/sim/sim_config.go @@ -32,12 +32,42 @@ var ( // GetSimulatorFlags gets the values of all the available simulation flags func GetSimulatorFlags() { // config fields - flag.StringVar(&FlagGenesisFileValue, "Genesis", "", "custom simulation genesis file; cannot be used with params file") - flag.StringVar(&FlagParamsFileValue, "Params", "", "custom simulation params file which overrides any random params; cannot be used with genesis") - flag.StringVar(&FlagExportParamsPathValue, "ExportParamsPath", "", "custom file path to save the exported params JSON") - flag.IntVar(&FlagExportParamsHeightValue, "ExportParamsHeight", 0, "height to which export the randomly generated params") - flag.StringVar(&FlagExportStatePathValue, "ExportStatePath", "", "custom file path to save the exported app state JSON") - flag.StringVar(&FlagExportStatsPathValue, "ExportStatsPath", "", "custom file path to save the exported simulation statistics JSON") + flag.StringVar( + &FlagGenesisFileValue, + "Genesis", + "", + "custom simulation genesis file; cannot be used with params file", + ) + flag.StringVar( + &FlagParamsFileValue, + "Params", + "", + "custom simulation params file which overrides any random params; cannot be used with genesis", + ) + flag.StringVar( + &FlagExportParamsPathValue, + "ExportParamsPath", + "", + "custom file path to save the exported params JSON", + ) + flag.IntVar( + &FlagExportParamsHeightValue, + "ExportParamsHeight", + 0, + "height to which export the randomly generated params", + ) + flag.StringVar( + &FlagExportStatePathValue, + "ExportStatePath", + "", + "custom file path to save the exported app state JSON", + ) + flag.StringVar( + &FlagExportStatsPathValue, + "ExportStatsPath", + "", + "custom file path to save the exported simulation statistics JSON", + ) flag.Int64Var(&FlagSeedValue, "Seed", 42, "simulation random seed") flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", 1, "initial block to start the simulation") flag.IntVar(&FlagNumBlocksValue, "NumBlocks", 500, "number of new blocks to simulate from the initial block height") @@ -45,13 +75,23 @@ func GetSimulatorFlags() { flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output") flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit") flag.BoolVar(&FlagOnOperationValue, "SimulateEveryOperation", false, "run slow invariants every operation") - flag.BoolVar(&FlagAllInvariantsValue, "PrintAllInvariants", false, "print all invariants if a broken invariant is found") + flag.BoolVar( + &FlagAllInvariantsValue, + "PrintAllInvariants", + false, + "print all invariants if a broken invariant is found", + ) // simulation flags flag.BoolVar(&FlagEnabledValue, "Enabled", false, "enable the simulation") flag.BoolVar(&FlagVerboseValue, "Verbose", false, "verbose log output") flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions") - flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", 0, "override genesis UNIX time instead of using a random UNIX time") + flag.Int64Var( + &FlagGenesisTimeValue, + "GenesisTime", + 0, + "override genesis UNIX time instead of using a random UNIX time", + ) } // NewConfigFromFlags creates a simulation from the retrieved values of the flags. diff --git a/tests/simulation/sim/sim_state.go b/tests/simulation/sim/sim_state.go index c4f884b9b4..2f314b6c78 100644 --- a/tests/simulation/sim/sim_state.go +++ b/tests/simulation/sim/sim_state.go @@ -33,7 +33,11 @@ const ( // 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, genesisState map[string]json.RawMessage) simtypes.AppStateFn { +func AppStateFn( + cdc codec.Codec, + 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 FlagGenesisTimeValue == 0 { @@ -74,11 +78,27 @@ func AppStateFn(cdc codec.Codec, simManager *module.SimulationManager, genesisSt if err != nil { panic(err) } - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) + appState, simAccs = AppStateRandomizedFn( + simManager, + r, + cdc, + accs, + genesisTimestamp, + appParams, + genesisState, + ) default: appParams := make(simtypes.AppParams) - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) + appState, simAccs = AppStateRandomizedFn( + simManager, + r, + cdc, + accs, + genesisTimestamp, + appParams, + genesisState, + ) } rawState := make(map[string]json.RawMessage) @@ -223,7 +243,11 @@ 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, error) { +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) diff --git a/tests/simulation/sim/sim_utils.go b/tests/simulation/sim/sim_utils.go index a1e25fb8d7..b310d7cae2 100644 --- a/tests/simulation/sim/sim_utils.go +++ b/tests/simulation/sim/sim_utils.go @@ -9,12 +9,17 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/zeta-chain/ethermint/app" evmante "github.com/zeta-chain/ethermint/app/ante" + zetaapp "github.com/zeta-chain/node/app" "github.com/zeta-chain/node/app/ante" ) -func NewSimApp(logger log.Logger, db dbm.DB, appOptions servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) (*zetaapp.App, error) { - +func NewSimApp( + logger log.Logger, + db dbm.DB, + appOptions servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), +) (*zetaapp.App, error) { encCdc := zetaapp.MakeEncodingConfig() // Set load latest version to false as we manually set it later. diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index ffb48f1f95..7d3d8305da 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -80,11 +80,23 @@ func TestAppStateDeterminism(t *testing.T) { } // For the same seed, the app hash produced at the end of each run should be the same for j := 0; j < numTimesToRunPerSeed; j++ { - db, dir, logger, _, err := cosmossimutils.SetupSimulation(config, SimDBBackend, SimDBName, simutils.FlagVerboseValue, simutils.FlagEnabledValue) + db, dir, logger, _, err := cosmossimutils.SetupSimulation( + config, + SimDBBackend, + SimDBName, + simutils.FlagVerboseValue, + simutils.FlagEnabledValue, + ) require.NoError(t, err) appOptions[flags.FlagHome] = dir - simApp, err := simutils.NewSimApp(logger, db, appOptions, interBlockCacheOpt(), baseapp.SetChainID(SimAppChainID)) + simApp, err := simutils.NewSimApp( + logger, + db, + appOptions, + interBlockCacheOpt(), + baseapp.SetChainID(SimAppChainID), + ) fmt.Printf( "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", @@ -98,7 +110,11 @@ func TestAppStateDeterminism(t *testing.T) { t, os.Stdout, simApp.BaseApp, - simutils.AppStateFn(simApp.AppCodec(), simApp.SimulationManager(), simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec())), + simutils.AppStateFn( + simApp.AppCodec(), + simApp.SimulationManager(), + simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec()), + ), cosmossim.RandomAccounts, cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), blockedAddresses, @@ -114,8 +130,15 @@ func TestAppStateDeterminism(t *testing.T) { if j != 0 { require.Equal( - t, string(appHashList[0]), string(appHashList[j]), - "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + t, + string(appHashList[0]), + string(appHashList[j]), + "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, + i+1, + numSeeds, + j+1, + numTimesToRunPerSeed, ) } } @@ -132,7 +155,13 @@ func TestFullAppSimulation(t *testing.T) { config.BlockMaxGas = SimBlockMaxGas config.DBBackend = SimDBBackend - db, dir, logger, skip, err := cosmossimutils.SetupSimulation(config, SimDBBackend, SimDBName, simutils.FlagVerboseValue, simutils.FlagEnabledValue) + db, dir, logger, skip, err := cosmossimutils.SetupSimulation( + config, + SimDBBackend, + SimDBName, + simutils.FlagVerboseValue, + simutils.FlagEnabledValue, + ) if skip { t.Skip("skipping application simulation") } @@ -154,7 +183,11 @@ func TestFullAppSimulation(t *testing.T) { t, os.Stdout, simApp.BaseApp, - simutils.AppStateFn(simApp.AppCodec(), simApp.SimulationManager(), simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec())), + simutils.AppStateFn( + simApp.AppCodec(), + simApp.SimulationManager(), + simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec()), + ), cosmossim.RandomAccounts, cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), blockedAddresses, From cad3f4fc72a37da5773ba1ff529d08549a6b91d2 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 10:50:11 +0530 Subject: [PATCH 11/22] add todos for BasicManager --- app/app.go | 88 ++++++++-------------- app/config.go | 2 +- app/encoding.go | 2 +- app/genesis.go | 21 ------ app/init_genesis.go | 66 ----------------- app/modules.go | 114 +++++++++++++++++++++++------ tests/simulation/sim/sim_config.go | 2 +- 7 files changed, 124 insertions(+), 171 deletions(-) delete mode 100644 app/genesis.go delete mode 100644 app/init_genesis.go diff --git a/app/app.go b/app/app.go index 3f8c295b31..86955375d7 100644 --- a/app/app.go +++ b/app/app.go @@ -1,6 +1,7 @@ package app import ( + "encoding/json" "io" "net/http" "os" @@ -177,64 +178,33 @@ func getGovProposalHandlers() []govclient.ProposalHandler { return govProposalHandlers } -var ( - ModuleBasics = module.NewBasicManager( - auth.AppModuleBasic{}, - genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), - bank.AppModuleBasic{}, - //capability.AppModuleBasic{}, - staking.AppModuleBasic{}, - distr.AppModuleBasic{}, - gov.NewAppModuleBasic(getGovProposalHandlers()), - params.AppModuleBasic{}, - crisis.AppModuleBasic{}, - slashing.AppModuleBasic{}, - //ibc.AppModuleBasic{}, - //ibctm.AppModuleBasic{}, - upgrade.AppModuleBasic{}, - evidence.AppModuleBasic{}, - //transfer.AppModuleBasic{}, - vesting.AppModuleBasic{}, - consensus.AppModuleBasic{}, - evm.AppModuleBasic{}, - feemarket.AppModuleBasic{}, - authoritymodule.AppModuleBasic{}, - lightclientmodule.AppModuleBasic{}, - crosschainmodule.AppModuleBasic{}, - //ibccrosschain.AppModuleBasic{}, - observermodule.AppModuleBasic{}, - fungiblemodule.AppModuleBasic{}, - emissionsmodule.AppModuleBasic{}, - groupmodule.AppModuleBasic{}, - authzmodule.AppModuleBasic{}, - ) - - // module account permissions - maccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - govtypes.ModuleName: {authtypes.Burner}, - //ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - crosschaintypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - //ibccrosschaintypes.ModuleName: nil, - evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - fungibletypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - emissionstypes.ModuleName: nil, - emissionstypes.UndistributedObserverRewardsPool: nil, - emissionstypes.UndistributedTssRewardsPool: nil, - } +type GenesisState map[string]json.RawMessage + +// module account permissions +var maccPerms = map[string][]string{ + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + govtypes.ModuleName: {authtypes.Burner}, + //ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + crosschaintypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + //ibccrosschaintypes.ModuleName: nil, + evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + fungibletypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + emissionstypes.ModuleName: nil, + emissionstypes.UndistributedObserverRewardsPool: nil, + emissionstypes.UndistributedTssRewardsPool: nil, +} - // module accounts that are NOT allowed to receive tokens - blockedReceivingModAcc = map[string]bool{ - distrtypes.ModuleName: true, - authtypes.FeeCollectorName: true, - stakingtypes.BondedPoolName: true, - stakingtypes.NotBondedPoolName: true, - govtypes.ModuleName: true, - } -) +// module accounts that are NOT allowed to receive tokens +var blockedReceivingModAcc = map[string]bool{ + distrtypes.ModuleName: true, + authtypes.FeeCollectorName: true, + stakingtypes.BondedPoolName: true, + stakingtypes.NotBondedPoolName: true, + govtypes.ModuleName: true, +} var ( _ runtime.AppI = (*App)(nil) @@ -738,7 +708,7 @@ func New( authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ) - app.ModuleBasics = newBasicManagerFromManager(app) + app.ModuleBasics = ModuleBasics // During begin block slashing happens after distr.BeginBlocker so that // there is nothing left over in the validator fee pool, so as to keep the @@ -906,7 +876,7 @@ func (app *App) ModuleAccountAddrs() map[string]bool { return modAccAddrs } -// LegacyAmino returns SimApp's amino codec. +// LegacyAmino returns app's amino codec. // // NOTE: This is solely to be used for testing purposes as it may be desirable // for modules to register their own custom testing types. diff --git a/app/config.go b/app/config.go index 8f50ff8b7b..3aae668605 100644 --- a/app/config.go +++ b/app/config.go @@ -20,7 +20,7 @@ var ( FlagBlockSizeValue int FlagLeanValue bool FlagCommitValue bool - FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation + FlagOnOperationValue bool FlagAllInvariantsValue bool FlagEnabledValue bool diff --git a/app/encoding.go b/app/encoding.go index 2e8c728b0f..755b4ccbae 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -14,7 +14,6 @@ import ( evmenc "github.com/zeta-chain/ethermint/encoding" ethermint "github.com/zeta-chain/ethermint/types" evmtypes "github.com/zeta-chain/ethermint/x/evm/types" - authoritytypes "github.com/zeta-chain/node/x/authority/types" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" emissionstypes "github.com/zeta-chain/node/x/emissions/types" @@ -28,6 +27,7 @@ func MakeEncodingConfig() ethermint.EncodingConfig { encodingConfig := evmenc.MakeConfig(ModuleBasics) registry := encodingConfig.InterfaceRegistry + // TODO test if we need to register these interfaces again as MakeConfig already registers them cryptocodec.RegisterInterfaces(registry) authtypes.RegisterInterfaces(registry) authz.RegisterInterfaces(registry) diff --git a/app/genesis.go b/app/genesis.go deleted file mode 100644 index 5bf0c1da80..0000000000 --- a/app/genesis.go +++ /dev/null @@ -1,21 +0,0 @@ -package app - -import ( - "encoding/json" - - "github.com/cosmos/cosmos-sdk/codec" -) - -// The genesis state of the blockchain is represented here as a map of raw json -// messages key'd by a identifier string. -// The identifier is used to determine which module genesis information belongs -// to so it may be appropriately routed during init chain. -// Within this application default genesis information is retrieved from -// the ModuleBasicManager which populates json from each BasicModule -// object provided to it during init. -type GenesisState map[string]json.RawMessage - -// NewDefaultGenesisState generates the default state for the application. -func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { - return ModuleBasics.DefaultGenesis(cdc) -} diff --git a/app/init_genesis.go b/app/init_genesis.go deleted file mode 100644 index b69972dbf8..0000000000 --- a/app/init_genesis.go +++ /dev/null @@ -1,66 +0,0 @@ -package app - -import ( - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" - "github.com/cosmos/cosmos-sdk/x/authz" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/group" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - evmtypes "github.com/zeta-chain/ethermint/x/evm/types" - feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" - - authoritytypes "github.com/zeta-chain/node/x/authority/types" - crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" - emissionsModuleTypes "github.com/zeta-chain/node/x/emissions/types" - fungibleModuleTypes "github.com/zeta-chain/node/x/fungible/types" - lightclienttypes "github.com/zeta-chain/node/x/lightclient/types" - observertypes "github.com/zeta-chain/node/x/observer/types" -) - -// InitGenesisModuleList returns the module list for genesis initialization -// NOTE: Capability module must occur first so that it can initialize any capabilities -// TODO: enable back IBC -// all commented lines in this function are modules related to IBC -// https://github.com/zeta-chain/node/issues/2573 -func InitGenesisModuleList() []string { - return []string{ - //capabilitytypes.ModuleName, - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - //ibcexported.ModuleName, - //ibctransfertypes.ModuleName, - evmtypes.ModuleName, - feemarkettypes.ModuleName, - paramstypes.ModuleName, - group.ModuleName, - genutiltypes.ModuleName, - upgradetypes.ModuleName, - evidencetypes.ModuleName, - vestingtypes.ModuleName, - observertypes.ModuleName, - crosschaintypes.ModuleName, - //ibccrosschaintypes.ModuleName, - fungibleModuleTypes.ModuleName, - emissionsModuleTypes.ModuleName, - authz.ModuleName, - authoritytypes.ModuleName, - lightclienttypes.ModuleName, - consensusparamtypes.ModuleName, - // NOTE: crisis module must go at the end to check for invariants on each module - crisistypes.ModuleName, - } -} diff --git a/app/modules.go b/app/modules.go index c94872305b..b041cc0d1a 100644 --- a/app/modules.go +++ b/app/modules.go @@ -1,59 +1,129 @@ package app import ( - "fmt" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" "github.com/cosmos/cosmos-sdk/x/bank" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/consensus" + consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types" + "github.com/cosmos/cosmos-sdk/x/crisis" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" distr "github.com/cosmos/cosmos-sdk/x/distribution" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/evidence" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/group" groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" "github.com/cosmos/cosmos-sdk/x/params" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/cosmos-sdk/x/upgrade" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/zeta-chain/ethermint/x/evm" evmtypes "github.com/zeta-chain/ethermint/x/evm/types" + "github.com/zeta-chain/ethermint/x/feemarket" + feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" + authoritymodule "github.com/zeta-chain/node/x/authority" + authoritytypes "github.com/zeta-chain/node/x/authority/types" + crosschainmodule "github.com/zeta-chain/node/x/crosschain" + crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" + emissionsmodule "github.com/zeta-chain/node/x/emissions" + emissionsModuleTypes "github.com/zeta-chain/node/x/emissions/types" + fungiblemodule "github.com/zeta-chain/node/x/fungible" + fungibleModuleTypes "github.com/zeta-chain/node/x/fungible/types" + lightclientmodule "github.com/zeta-chain/node/x/lightclient" + lightclienttypes "github.com/zeta-chain/node/x/lightclient/types" + observermodule "github.com/zeta-chain/node/x/observer" + observertypes "github.com/zeta-chain/node/x/observer/types" ) // ModuleBasics defines the module BasicManager that is in charge of setting up basic, // non-dependant module elements, such as codec registration // and genesis verification. -func newBasicManagerFromManager(app *App) module.BasicManager { - moduleBasics := make([]module.AppModuleBasic, 0) - for _, m := range app.mm.Modules { - m, ok := m.(module.AppModuleBasic) - if !ok { - fmt.Printf("module %s is not an instance of module.AppModuleBasic\n", m) - continue - } - if m.Name() == govtypes.ModuleName { - m = gov.NewAppModuleBasic(getGovProposalHandlers()) - } - if m.Name() == genutiltypes.ModuleName { - m = genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator) - } +// TODO: Use app.mm to create the basic manager instead +var ModuleBasics = module.NewBasicManager( + auth.AppModuleBasic{}, + genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + bank.AppModuleBasic{}, + //capability.AppModuleBasic{}, + staking.AppModuleBasic{}, + distr.AppModuleBasic{}, + gov.NewAppModuleBasic(getGovProposalHandlers()), + params.AppModuleBasic{}, + crisis.AppModuleBasic{}, + slashing.AppModuleBasic{}, + //ibc.AppModuleBasic{}, + //ibctm.AppModuleBasic{}, + upgrade.AppModuleBasic{}, + evidence.AppModuleBasic{}, + //transfer.AppModuleBasic{}, + vesting.AppModuleBasic{}, + consensus.AppModuleBasic{}, + evm.AppModuleBasic{}, + feemarket.AppModuleBasic{}, + authoritymodule.AppModuleBasic{}, + lightclientmodule.AppModuleBasic{}, + crosschainmodule.AppModuleBasic{}, + //ibccrosschain.AppModuleBasic{}, + observermodule.AppModuleBasic{}, + fungiblemodule.AppModuleBasic{}, + emissionsmodule.AppModuleBasic{}, + groupmodule.AppModuleBasic{}, + authzmodule.AppModuleBasic{}, +) - moduleBasics = append(moduleBasics, m) +// InitGenesisModuleList returns the module list for genesis initialization +// NOTE: Capability module must occur first so that it can initialize any capabilities +// TODO: enable back IBC +// all commented lines in this function are modules related to IBC +// https://github.com/zeta-chain/node/issues/2573 +func InitGenesisModuleList() []string { + return []string{ + //capabilitytypes.ModuleName, + authtypes.ModuleName, + banktypes.ModuleName, + distrtypes.ModuleName, + stakingtypes.ModuleName, + slashingtypes.ModuleName, + govtypes.ModuleName, + //ibcexported.ModuleName, + //ibctransfertypes.ModuleName, + evmtypes.ModuleName, + feemarkettypes.ModuleName, + paramstypes.ModuleName, + group.ModuleName, + genutiltypes.ModuleName, + upgradetypes.ModuleName, + evidencetypes.ModuleName, + vestingtypes.ModuleName, + observertypes.ModuleName, + crosschaintypes.ModuleName, + //ibccrosschaintypes.ModuleName, + fungibleModuleTypes.ModuleName, + emissionsModuleTypes.ModuleName, + authz.ModuleName, + authoritytypes.ModuleName, + lightclienttypes.ModuleName, + consensusparamtypes.ModuleName, + // NOTE: crisis module must go at the end to check for invariants on each module + crisistypes.ModuleName, } - basicManager := module.NewBasicManager(moduleBasics...) - //basicManager.RegisterLegacyAminoCodec(app.cdc) - basicManager.RegisterInterfaces(app.interfaceRegistry) - - return basicManager } func simulationModules( diff --git a/tests/simulation/sim/sim_config.go b/tests/simulation/sim/sim_config.go index 98d2ffb6d9..915a77dd40 100644 --- a/tests/simulation/sim/sim_config.go +++ b/tests/simulation/sim/sim_config.go @@ -20,7 +20,7 @@ var ( FlagBlockSizeValue int FlagLeanValue bool FlagCommitValue bool - FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation + FlagOnOperationValue bool FlagAllInvariantsValue bool FlagEnabledValue bool From c07d5194747909defbdab1e2c98ea48a7d858e6b Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 12:32:28 +0530 Subject: [PATCH 12/22] add todos for BasicManager --- app/encoding.go | 1 + app/modules.go | 16 +++++++++------- sims.mk | 27 ++++++++++++++++----------- tests/simulation/sim/sim_config.go | 15 +++++++++++---- tests/simulation/sim_test.go | 4 ++++ 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/app/encoding.go b/app/encoding.go index 755b4ccbae..44748dacee 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -14,6 +14,7 @@ import ( evmenc "github.com/zeta-chain/ethermint/encoding" ethermint "github.com/zeta-chain/ethermint/types" evmtypes "github.com/zeta-chain/ethermint/x/evm/types" + authoritytypes "github.com/zeta-chain/node/x/authority/types" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" emissionstypes "github.com/zeta-chain/node/x/emissions/types" diff --git a/app/modules.go b/app/modules.go index b041cc0d1a..038b3766aa 100644 --- a/app/modules.go +++ b/app/modules.go @@ -38,6 +38,7 @@ import ( evmtypes "github.com/zeta-chain/ethermint/x/evm/types" "github.com/zeta-chain/ethermint/x/feemarket" feemarkettypes "github.com/zeta-chain/ethermint/x/feemarket/types" + authoritymodule "github.com/zeta-chain/node/x/authority" authoritytypes "github.com/zeta-chain/node/x/authority/types" crosschainmodule "github.com/zeta-chain/node/x/crosschain" @@ -126,6 +127,7 @@ func InitGenesisModuleList() []string { } } +// simulationModules returns a list of modules to include in the simulation func simulationModules( app *App, appCodec codec.Codec, @@ -139,13 +141,13 @@ func simulationModules( app.GetSubspace(authtypes.ModuleName), ), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - gov.NewAppModule( - appCodec, - &app.GovKeeper, - app.AccountKeeper, - app.BankKeeper, - app.GetSubspace(govtypes.ModuleName), - ), + //gov.NewAppModule( + // appCodec, + // &app.GovKeeper, + // app.AccountKeeper, + // app.BankKeeper, + // app.GetSubspace(govtypes.ModuleName), + //), staking.NewAppModule( appCodec, app.StakingKeeper, diff --git a/sims.mk b/sims.mk index db4b4d7a5c..ea81e40807 100644 --- a/sims.mk +++ b/sims.mk @@ -10,27 +10,32 @@ SIMAPP = ./tests/simulation # Run sim is a cosmos tool which helps us to run multiple simulations in parallel. runsim: $(BINDIR)/runsim $(BINDIR)/runsim: - @echo "Installing runsim..." - @(cd /tmp && go install github.com/cosmos/tools/cmd/runsim@v1.0.0) + @echo 'Installing runsim...' + @TEMP_DIR=$$(mktemp -d) && \ + cd $$TEMP_DIR && \ + go install github.com/cosmos/tools/cmd/runsim@v1.0.0 && \ + rm -rf $$TEMP_DIR || (echo 'Failed to install runsim' && exit 1) + @echo 'runsim installed successfully' -test-sim-nondeterminism: - @echo "Running non-determinism test..." - @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ - -NumBlocks=10 -BlockSize=20 -Commit=true -Period=0 -v -timeout 24h +define run-sim-test + @echo "Running $(1)..." + @go test -mod=readonly $(SIMAPP) -run $(2) -Enabled=true \ + -NumBlocks=$(3) -BlockSize=$(4) -Commit=true -Period=0 -v -timeout $(5) +endef +test-sim-nondeterminism: + $(call run-sim-test,"non-determinism test",TestAppStateDeterminism,100,200,2h) test-sim-fullappsimulation: - @echo "Running TestFullAppSimulation." - @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Enabled=true \ - -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + $(call run-sim-test,"TestFullAppSimulation",TestFullAppSimulation,100,200,2h) test-sim-multi-seed-long: runsim - @echo "Running long multi-seed application simulation. This may take awhile!" + @echo "Running long multi-seed application simulation." @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation test-sim-multi-seed-short: runsim - @echo "Running short multi-seed application simulation. This may take awhile!" + @echo "Running short multi-seed application simulation." @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation diff --git a/tests/simulation/sim/sim_config.go b/tests/simulation/sim/sim_config.go index 915a77dd40..c306f47f54 100644 --- a/tests/simulation/sim/sim_config.go +++ b/tests/simulation/sim/sim_config.go @@ -6,6 +6,13 @@ import ( "github.com/cosmos/cosmos-sdk/types/simulation" ) +const ( + defaultSeed = 42 + defaultNumBlocks = 500 + defaultInitialHeight = 1 + defaultBlockSize = 200 +) + // List of available flags for the simulator var ( FlagGenesisFileValue string @@ -68,10 +75,10 @@ func GetSimulatorFlags() { "", "custom file path to save the exported simulation statistics JSON", ) - flag.Int64Var(&FlagSeedValue, "Seed", 42, "simulation random seed") - flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", 1, "initial block to start the simulation") - flag.IntVar(&FlagNumBlocksValue, "NumBlocks", 500, "number of new blocks to simulate from the initial block height") - flag.IntVar(&FlagBlockSizeValue, "BlockSize", 200, "operations per block") + flag.Int64Var(&FlagSeedValue, "Seed", defaultSeed, "simulation random seed") + flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", defaultInitialHeight, "initial block to start the simulation") + flag.IntVar(&FlagNumBlocksValue, "NumBlocks", defaultNumBlocks, "number of new blocks to simulate from the initial block height") + flag.IntVar(&FlagBlockSizeValue, "BlockSize", defaultBlockSize, "operations per block") flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output") flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit") flag.BoolVar(&FlagOnOperationValue, "SimulateEveryOperation", false, "run slow invariants every operation") diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 7d3d8305da..3b313338f4 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -128,6 +128,10 @@ func TestAppStateDeterminism(t *testing.T) { appHash := simApp.LastCommitID().Hash appHashList[j] = appHash + // Clean up resources + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + if j != 0 { require.Equal( t, From 4f3ebbe3c81a6bd7a01de4eb2c74f5d2344f571f Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 12:54:20 +0530 Subject: [PATCH 13/22] add cleanup for TestFullAppSimulation --- app/config.go | 2 +- tests/simulation/sim_test.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/config.go b/app/config.go index 3aae668605..8f50ff8b7b 100644 --- a/app/config.go +++ b/app/config.go @@ -20,7 +20,7 @@ var ( FlagBlockSizeValue int FlagLeanValue bool FlagCommitValue bool - FlagOnOperationValue bool + FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation FlagAllInvariantsValue bool FlagEnabledValue bool diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 3b313338f4..3fe882fe79 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -209,4 +209,8 @@ func TestFullAppSimulation(t *testing.T) { } simutils.PrintStats(db) + + // Clean up resources + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) } From 56b469858b6ba01939cea9cc5c2b2f05dd56d904 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 13:17:34 +0530 Subject: [PATCH 14/22] register legacy router --- app/app.go | 4 ++++ app/modules.go | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 86955375d7..6e0a86b01b 100644 --- a/app/app.go +++ b/app/app.go @@ -607,6 +607,7 @@ func New( govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler). AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)) + govConfig := govtypes.DefaultConfig() govKeeper := govkeeper.NewKeeper( appCodec, @@ -618,11 +619,14 @@ func New( govConfig, authAddr, ) + app.GovKeeper = *govKeeper.SetHooks( govtypes.NewMultiGovHooks( // register governance hooks ), ) + // Set legacy router for backwards compatibility with gov v1beta1 + app.GovKeeper.SetLegacyRouter(govRouter) // Create evidence Keeper for to register the IBC light client misbehaviour evidence route evidenceKeeper := evidencekeeper.NewKeeper( diff --git a/app/modules.go b/app/modules.go index 038b3766aa..3324680902 100644 --- a/app/modules.go +++ b/app/modules.go @@ -141,13 +141,13 @@ func simulationModules( app.GetSubspace(authtypes.ModuleName), ), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - //gov.NewAppModule( - // appCodec, - // &app.GovKeeper, - // app.AccountKeeper, - // app.BankKeeper, - // app.GetSubspace(govtypes.ModuleName), - //), + gov.NewAppModule( + appCodec, + &app.GovKeeper, + app.AccountKeeper, + app.BankKeeper, + app.GetSubspace(govtypes.ModuleName), + ), staking.NewAppModule( appCodec, app.StakingKeeper, From c1db4cf4cedc9086d3e3c67a820aea587149f513 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 20:46:25 +0530 Subject: [PATCH 15/22] added a doc for simulation testing --- docs/development/SIMULATION_TESTING.md | 13 +++++++++++++ readme.md | 1 + 2 files changed, 14 insertions(+) create mode 100644 docs/development/SIMULATION_TESTING.md diff --git a/docs/development/SIMULATION_TESTING.md b/docs/development/SIMULATION_TESTING.md new file mode 100644 index 0000000000..332f6710a3 --- /dev/null +++ b/docs/development/SIMULATION_TESTING.md @@ -0,0 +1,13 @@ +# Zetachain simulation testing + + +## Running the simulation tests + +The simulation tests can be run with the following command: +```bash + +make -f sims.mk test-sim-nondeterminism +make -f sims.mk test-sim-fullappsimulation +make -f sims.mk test-sim-multi-seed-long +make -f sims.mk test-sim-multi-seed-short +``` \ No newline at end of file diff --git a/readme.md b/readme.md index 61f04f632f..89a5befb3a 100644 --- a/readme.md +++ b/readme.md @@ -73,6 +73,7 @@ Find below further documentation for development and running your own ZetaChain - [Run the E2E tests and interact with the localnet](docs/development/LOCAL_TESTING.md) - [Make a new ZetaChain release](docs/development/RELEASES.md) - [Deploy your own ZetaChain or Bitcoin node](docs/development/DEPLOY_NODES.md) +- [Run the simulation tests](docs/development/SIMULATION_TESTING.md) ## Community From d98add5809b3f31a3ea9e42713e41d4abac589d8 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 3 Oct 2024 20:52:27 +0530 Subject: [PATCH 16/22] undo db close for multi threaded test --- tests/simulation/sim_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 3fe882fe79..3b313338f4 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -209,8 +209,4 @@ func TestFullAppSimulation(t *testing.T) { } simutils.PrintStats(db) - - // Clean up resources - require.NoError(t, db.Close()) - require.NoError(t, os.RemoveAll(dir)) } From bff41210668ed41ce0bb8c5c4600fac5d39ac8cb Mon Sep 17 00:00:00 2001 From: Tanmay Date: Mon, 14 Oct 2024 10:20:16 +0530 Subject: [PATCH 17/22] add description for tests --- Makefile | 55 ++++++++++++++++++++++++++ app/encoding.go | 1 + changelog.md | 2 +- docs/development/SIMULATION_TESTING.md | 36 ++++++++++++++--- sims.mk | 48 ---------------------- tests/simulation/sim/sim_config.go | 14 ++++++- tests/simulation/sim_test.go | 13 +++--- 7 files changed, 106 insertions(+), 63 deletions(-) delete mode 100644 sims.mk diff --git a/Makefile b/Makefile index b3fbf4009a..bd7b0df002 100644 --- a/Makefile +++ b/Makefile @@ -345,6 +345,61 @@ start-upgrade-import-mainnet-test: zetanode-upgrade export UPGRADE_HEIGHT=225 && \ cd contrib/localnet/ && ./scripts/import-data.sh mainnet && $(DOCKER_COMPOSE) --profile upgrade -f docker-compose.yml -f docker-compose-upgrade.yml up -d + +############################################################################### +### Simulation Tests ### +############################################################################### + +BINDIR ?= $(GOPATH)/bin +SIMAPP = ./tests/simulation + + +# Run sim is a cosmos tool which helps us to run multiple simulations in parallel. +runsim: $(BINDIR)/runsim +$(BINDIR)/runsim: + @echo 'Installing runsim...' + @TEMP_DIR=$$(mktemp -d) && \ + cd $$TEMP_DIR && \ + go install github.com/cosmos/tools/cmd/runsim@v1.0.0 && \ + rm -rf $$TEMP_DIR || (echo 'Failed to install runsim' && exit 1) + @echo 'runsim installed successfully' + + +# Configuaration parameters for simulation tests +# NumBlocks: Number of blocks to simulate +# BlockSize: Number of transactions in a block +# Commit: Whether to commit the block or not +# Period: Invariant check period +# Timeout: Timeout for the simulation test +define run-sim-test + @echo "Running $(1)..." + @go test -mod=readonly $(SIMAPP) -run $(2) -Enabled=true \ + -NumBlocks=$(3) -BlockSize=$(4) -Commit=true -Period=0 -v -timeout $(5) +endef + +test-sim-nondeterminism: + $(call run-sim-test,"non-determinism test",TestAppStateDeterminism,100,200,2h) + +test-sim-fullappsimulation: + $(call run-sim-test,"TestFullAppSimulation",TestFullAppSimulation,100,200,2h) + +test-sim-multi-seed-long: runsim + @echo "Running long multi-seed application simulation." + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation + +test-sim-multi-seed-short: runsim + @echo "Running short multi-seed application simulation." + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation + + + +.PHONY: \ +test-sim-nondeterminism \ +test-sim-fullappsimulation \ +test-sim-multi-seed-long \ +test-sim-multi-seed-short + + ############################################################################### ### GoReleaser ### ############################################################################### diff --git a/app/encoding.go b/app/encoding.go index 44748dacee..674887f670 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -29,6 +29,7 @@ func MakeEncodingConfig() ethermint.EncodingConfig { registry := encodingConfig.InterfaceRegistry // TODO test if we need to register these interfaces again as MakeConfig already registers them + // https://github.com/zeta-chain/node/issues/3003 cryptocodec.RegisterInterfaces(registry) authtypes.RegisterInterfaces(registry) authz.RegisterInterfaces(registry) diff --git a/changelog.md b/changelog.md index 6069bac909..b76c8bba4d 100644 --- a/changelog.md +++ b/changelog.md @@ -36,7 +36,7 @@ * [2874](https://github.com/zeta-chain/node/pull/2874) - add support for multiple runs for precompile tests * [2895](https://github.com/zeta-chain/node/pull/2895) - add e2e test for bitcoin deposit and call * [2894](https://github.com/zeta-chain/node/pull/2894) - increase gas limit for TSS vote tx -* [2947](https://github.com/zeta-chain/node/pull/2947/) - add simulation tests +* [2947](https://github.com/zeta-chain/node/pull/2947/) - initialize simulation tests ### Fixes diff --git a/docs/development/SIMULATION_TESTING.md b/docs/development/SIMULATION_TESTING.md index 332f6710a3..c14e2e2713 100644 --- a/docs/development/SIMULATION_TESTING.md +++ b/docs/development/SIMULATION_TESTING.md @@ -1,13 +1,37 @@ # Zetachain simulation testing -## Running the simulation tests -The simulation tests can be run with the following command: +## Overview +The blockchain simulation tests how the blockchain application would behave under real life circumstances by generating +and sending randomized messages.The goal of this is to detect and debug failures that could halt a live chain,by providing +logs and statistics about the operations run by the simulator as well as exporting the latest application state. + + +## Simulation tests + +### Nondeterminism test +Nondeterminism test runs a full application simulation , and produces multiple blocks as per the config +It checks the determinism of the application by comparing the apphash at the end of each run to other runs +The test certifies that , for the same set of operations ( irrespective of what the operations are ), we would reach the same final state if the initial state is the same +```bash +make test-sim-nondeterminism +``` +### Full application simulation test +Full application runs a full app simulation test with the provided configuration. +At the end of the run it tries to export the genesis state to make sure the export works. ```bash +make test-sim-full-app +``` -make -f sims.mk test-sim-nondeterminism -make -f sims.mk test-sim-fullappsimulation -make -f sims.mk test-sim-multi-seed-long -make -f sims.mk test-sim-multi-seed-short +### Multi seed long test +Multi seed long test runs a full application simulation with multiple seeds and multiple blocks.This runs the test for a longer duration compared to the multi seed short test +```bash +make test-sim-multi-seed-long +``` + +### Multi seed short test +Multi seed short test runs a full application simulation with multiple seeds and multiple blocks. This runs the test for a longer duration compared to the multi seed long test +```bash +make test-sim-multi-seed-short ``` \ No newline at end of file diff --git a/sims.mk b/sims.mk deleted file mode 100644 index ea81e40807..0000000000 --- a/sims.mk +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/make -f - -######################################## -### Simulations - -BINDIR ?= $(GOPATH)/bin -SIMAPP = ./tests/simulation - - -# Run sim is a cosmos tool which helps us to run multiple simulations in parallel. -runsim: $(BINDIR)/runsim -$(BINDIR)/runsim: - @echo 'Installing runsim...' - @TEMP_DIR=$$(mktemp -d) && \ - cd $$TEMP_DIR && \ - go install github.com/cosmos/tools/cmd/runsim@v1.0.0 && \ - rm -rf $$TEMP_DIR || (echo 'Failed to install runsim' && exit 1) - @echo 'runsim installed successfully' - - -define run-sim-test - @echo "Running $(1)..." - @go test -mod=readonly $(SIMAPP) -run $(2) -Enabled=true \ - -NumBlocks=$(3) -BlockSize=$(4) -Commit=true -Period=0 -v -timeout $(5) -endef - -test-sim-nondeterminism: - $(call run-sim-test,"non-determinism test",TestAppStateDeterminism,100,200,2h) - -test-sim-fullappsimulation: - $(call run-sim-test,"TestFullAppSimulation",TestFullAppSimulation,100,200,2h) - -test-sim-multi-seed-long: runsim - @echo "Running long multi-seed application simulation." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation - -test-sim-multi-seed-short: runsim - @echo "Running short multi-seed application simulation." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation - - - -.PHONY: \ -test-sim-nondeterminism \ -test-sim-fullappsimulation \ -test-sim-multi-seed-long \ -test-sim-multi-seed-short - diff --git a/tests/simulation/sim/sim_config.go b/tests/simulation/sim/sim_config.go index c306f47f54..8a6c281db8 100644 --- a/tests/simulation/sim/sim_config.go +++ b/tests/simulation/sim/sim_config.go @@ -76,8 +76,18 @@ func GetSimulatorFlags() { "custom file path to save the exported simulation statistics JSON", ) flag.Int64Var(&FlagSeedValue, "Seed", defaultSeed, "simulation random seed") - flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", defaultInitialHeight, "initial block to start the simulation") - flag.IntVar(&FlagNumBlocksValue, "NumBlocks", defaultNumBlocks, "number of new blocks to simulate from the initial block height") + flag.IntVar( + &FlagInitialBlockHeightValue, + "InitialBlockHeight", + defaultInitialHeight, + "initial block to start the simulation", + ) + flag.IntVar( + &FlagNumBlocksValue, + "NumBlocks", + defaultNumBlocks, + "number of new blocks to simulate from the initial block height", + ) flag.IntVar(&FlagBlockSizeValue, "BlockSize", defaultBlockSize, "operations per block") flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output") flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit") diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 3b313338f4..385767aeac 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -2,7 +2,6 @@ package simulation_test import ( "encoding/json" - "fmt" "math/rand" "os" "testing" @@ -30,8 +29,10 @@ func init() { const ( SimAppChainID = "simulation_777-1" SimBlockMaxGas = 815000000 - SimDBBackend = "goleveldb" - SimDBName = "simulation" + //github.com/zeta-chain/node/issues/3004 + // TODO : Support pebbleDB for simulation tests + SimDBBackend = "goleveldb" + SimDBName = "simulation" ) // interBlockCacheOpt returns a BaseApp option function that sets the persistent @@ -43,7 +44,7 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { // TestAppStateDeterminism runs a full application simulation , and produces multiple blocks as per the config // It checks the determinism of the application by comparing the apphash at the end of each run to other runs // The following test certifies that , for the same set of operations ( irrespective of what the operations are ) , -// we would reach the same final state if the initital state is the same +// we would reach the same final state if the initial state is the same func TestAppStateDeterminism(t *testing.T) { if !simutils.FlagEnabledValue { t.Skip("skipping application simulation") @@ -72,7 +73,7 @@ func TestAppStateDeterminism(t *testing.T) { appOptions := make(cosmossimutils.AppOptionsMap, 0) appOptions[server.FlagInvCheckPeriod] = simutils.FlagPeriodValue - fmt.Println("Running tests for numSeeds: ", numSeeds, " numTimesToRunPerSeed: ", numTimesToRunPerSeed) + t.Log("Running tests for numSeeds: ", numSeeds, " numTimesToRunPerSeed: ", numTimesToRunPerSeed) for i := 0; i < numSeeds; i++ { if config.Seed == cosmossimcli.DefaultSeedValue { @@ -98,7 +99,7 @@ func TestAppStateDeterminism(t *testing.T) { baseapp.SetChainID(SimAppChainID), ) - fmt.Printf( + t.Logf( "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, ) From 74b0ad7c2e62aa94826cebaaf1421e83523f15fb Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 15 Oct 2024 11:57:37 +0530 Subject: [PATCH 18/22] remove go module from simulation tests --- app/app.go | 2 +- app/modules.go | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/app.go b/app/app.go index 6e0a86b01b..619b33fd0b 100644 --- a/app/app.go +++ b/app/app.go @@ -626,7 +626,7 @@ func New( ), ) // Set legacy router for backwards compatibility with gov v1beta1 - app.GovKeeper.SetLegacyRouter(govRouter) + // app.GovKeeper.SetLegacyRouter(govRouter) // Create evidence Keeper for to register the IBC light client misbehaviour evidence route evidenceKeeper := evidencekeeper.NewKeeper( diff --git a/app/modules.go b/app/modules.go index 3324680902..c9800a2f61 100644 --- a/app/modules.go +++ b/app/modules.go @@ -141,13 +141,15 @@ func simulationModules( app.GetSubspace(authtypes.ModuleName), ), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), - gov.NewAppModule( - appCodec, - &app.GovKeeper, - app.AccountKeeper, - app.BankKeeper, - app.GetSubspace(govtypes.ModuleName), - ), + // Todo : Enable gov module simulation + // https://github.com/zeta-chain/node/issues/3007 + //gov.NewAppModule( + // appCodec, + // &app.GovKeeper, + // app.AccountKeeper, + // app.BankKeeper, + // app.GetSubspace(govtypes.ModuleName), + //), staking.NewAppModule( appCodec, app.StakingKeeper, From f8c095d8b9820bc8de07ac0e29c30dce0f991d8c Mon Sep 17 00:00:00 2001 From: Tanmay Date: Fri, 18 Oct 2024 12:34:53 -0400 Subject: [PATCH 19/22] make basicsmanager private --- app/app.go | 11 ++++++++--- app/modules.go | 2 +- tests/simulation/sim_test.go | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/app.go b/app/app.go index 619b33fd0b..703a970cba 100644 --- a/app/app.go +++ b/app/app.go @@ -229,7 +229,7 @@ type App struct { mm *module.Manager sm *module.SimulationManager - ModuleBasics module.BasicManager + mb module.BasicManager configurator module.Configurator // sdk keepers @@ -712,7 +712,7 @@ func New( authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ) - app.ModuleBasics = ModuleBasics + app.mb = ModuleBasics // During begin block slashing happens after distr.BeginBlocker so that // there is nothing left over in the validator fee pool, so as to keep the @@ -943,7 +943,7 @@ func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register legacy and grpc-gateway routes for all modules. - app.ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + app.mb.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // register app's OpenAPI routes. if apiConfig.Swagger { @@ -1035,6 +1035,11 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +func (app *App) BasicManager() module.BasicManager { + return app.mb + +} + func (app *App) BlockedAddrs() map[string]bool { blockList := make(map[string]bool) diff --git a/app/modules.go b/app/modules.go index c9800a2f61..6f164a9409 100644 --- a/app/modules.go +++ b/app/modules.go @@ -56,7 +56,7 @@ import ( // ModuleBasics defines the module BasicManager that is in charge of setting up basic, // non-dependant module elements, such as codec registration // and genesis verification. - +// https://github.com/zeta-chain/node/issues/3021 // TODO: Use app.mm to create the basic manager instead var ModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, diff --git a/tests/simulation/sim_test.go b/tests/simulation/sim_test.go index 385767aeac..957e92081a 100644 --- a/tests/simulation/sim_test.go +++ b/tests/simulation/sim_test.go @@ -114,7 +114,7 @@ func TestAppStateDeterminism(t *testing.T) { simutils.AppStateFn( simApp.AppCodec(), simApp.SimulationManager(), - simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec()), + simApp.BasicManager().DefaultGenesis(simApp.AppCodec()), ), cosmossim.RandomAccounts, cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), @@ -191,7 +191,7 @@ func TestFullAppSimulation(t *testing.T) { simutils.AppStateFn( simApp.AppCodec(), simApp.SimulationManager(), - simApp.ModuleBasics.DefaultGenesis(simApp.AppCodec()), + simApp.BasicManager().DefaultGenesis(simApp.AppCodec()), ), cosmossim.RandomAccounts, cosmossimutils.SimulationOperations(simApp, simApp.AppCodec(), config), From b49be6b4e376691da1883e9926ede4afe7dd4b08 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 22 Oct 2024 08:46:45 -0400 Subject: [PATCH 20/22] Update Makefile Co-authored-by: Francisco de Borja Aranda Castillejo --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bd7b0df002..f4aa4f5e47 100644 --- a/Makefile +++ b/Makefile @@ -365,7 +365,7 @@ $(BINDIR)/runsim: @echo 'runsim installed successfully' -# Configuaration parameters for simulation tests +# Configuration parameters for simulation tests # NumBlocks: Number of blocks to simulate # BlockSize: Number of transactions in a block # Commit: Whether to commit the block or not From cf4cb457293fe9d239303db98ca7bf46c1ae5848 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 22 Oct 2024 08:46:57 -0400 Subject: [PATCH 21/22] Update changelog.md Co-authored-by: Francisco de Borja Aranda Castillejo --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index b76c8bba4d..ecd222d1ef 100644 --- a/changelog.md +++ b/changelog.md @@ -36,7 +36,7 @@ * [2874](https://github.com/zeta-chain/node/pull/2874) - add support for multiple runs for precompile tests * [2895](https://github.com/zeta-chain/node/pull/2895) - add e2e test for bitcoin deposit and call * [2894](https://github.com/zeta-chain/node/pull/2894) - increase gas limit for TSS vote tx -* [2947](https://github.com/zeta-chain/node/pull/2947/) - initialize simulation tests +* [2947](https://github.com/zeta-chain/node/pull/2947) - initialize simulation tests ### Fixes From d5ae57c68df2a2adade97b8dce3ad98e2bcaad32 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 22 Oct 2024 08:58:57 -0400 Subject: [PATCH 22/22] format simulation.md --- app/app.go | 1 - docs/development/SIMULATION_TESTING.md | 3 --- 2 files changed, 4 deletions(-) diff --git a/app/app.go b/app/app.go index 703a970cba..971e6ce710 100644 --- a/app/app.go +++ b/app/app.go @@ -1037,7 +1037,6 @@ func (app *App) SimulationManager() *module.SimulationManager { func (app *App) BasicManager() module.BasicManager { return app.mb - } func (app *App) BlockedAddrs() map[string]bool { diff --git a/docs/development/SIMULATION_TESTING.md b/docs/development/SIMULATION_TESTING.md index c14e2e2713..1f5232911a 100644 --- a/docs/development/SIMULATION_TESTING.md +++ b/docs/development/SIMULATION_TESTING.md @@ -1,7 +1,4 @@ # Zetachain simulation testing - - - ## Overview The blockchain simulation tests how the blockchain application would behave under real life circumstances by generating and sending randomized messages.The goal of this is to detect and debug failures that could halt a live chain,by providing